Sync ACPICA with Intel's version 20160108.
[dragonfly.git] / sys / contrib / dev / acpica / source / components / events / evrgnini.c
1 /******************************************************************************
2  *
3  * Module Name: evrgnini- ACPI AddressSpace (OpRegion) init
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2016, 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 #include "acpi.h"
45 #include "accommon.h"
46 #include "acevents.h"
47 #include "acnamesp.h"
48
49 #define _COMPONENT          ACPI_EVENTS
50         ACPI_MODULE_NAME    ("evrgnini")
51
52 /* Local prototypes */
53
54 static BOOLEAN
55 AcpiEvIsPciRootBridge (
56     ACPI_NAMESPACE_NODE     *Node);
57
58
59 /*******************************************************************************
60  *
61  * FUNCTION:    AcpiEvSystemMemoryRegionSetup
62  *
63  * PARAMETERS:  Handle              - Region we are interested in
64  *              Function            - Start or stop
65  *              HandlerContext      - Address space handler context
66  *              RegionContext       - Region specific context
67  *
68  * RETURN:      Status
69  *
70  * DESCRIPTION: Setup a SystemMemory operation region
71  *
72  ******************************************************************************/
73
74 ACPI_STATUS
75 AcpiEvSystemMemoryRegionSetup (
76     ACPI_HANDLE             Handle,
77     UINT32                  Function,
78     void                    *HandlerContext,
79     void                    **RegionContext)
80 {
81     ACPI_OPERAND_OBJECT     *RegionDesc = (ACPI_OPERAND_OBJECT *) Handle;
82     ACPI_MEM_SPACE_CONTEXT  *LocalRegionContext;
83
84
85     ACPI_FUNCTION_TRACE (EvSystemMemoryRegionSetup);
86
87
88     if (Function == ACPI_REGION_DEACTIVATE)
89     {
90         if (*RegionContext)
91         {
92             LocalRegionContext = (ACPI_MEM_SPACE_CONTEXT *) *RegionContext;
93
94             /* Delete a cached mapping if present */
95
96             if (LocalRegionContext->MappedLength)
97             {
98                 AcpiOsUnmapMemory (LocalRegionContext->MappedLogicalAddress,
99                     LocalRegionContext->MappedLength);
100             }
101             ACPI_FREE (LocalRegionContext);
102             *RegionContext = NULL;
103         }
104         return_ACPI_STATUS (AE_OK);
105     }
106
107     /* Create a new context */
108
109     LocalRegionContext = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_MEM_SPACE_CONTEXT));
110     if (!(LocalRegionContext))
111     {
112         return_ACPI_STATUS (AE_NO_MEMORY);
113     }
114
115     /* Save the region length and address for use in the handler */
116
117     LocalRegionContext->Length  = RegionDesc->Region.Length;
118     LocalRegionContext->Address = RegionDesc->Region.Address;
119
120     *RegionContext = LocalRegionContext;
121     return_ACPI_STATUS (AE_OK);
122 }
123
124
125 /*******************************************************************************
126  *
127  * FUNCTION:    AcpiEvIoSpaceRegionSetup
128  *
129  * PARAMETERS:  Handle              - Region we are interested in
130  *              Function            - Start or stop
131  *              HandlerContext      - Address space handler context
132  *              RegionContext       - Region specific context
133  *
134  * RETURN:      Status
135  *
136  * DESCRIPTION: Setup a IO operation region
137  *
138  ******************************************************************************/
139
140 ACPI_STATUS
141 AcpiEvIoSpaceRegionSetup (
142     ACPI_HANDLE             Handle,
143     UINT32                  Function,
144     void                    *HandlerContext,
145     void                    **RegionContext)
146 {
147     ACPI_FUNCTION_TRACE (EvIoSpaceRegionSetup);
148
149
150     if (Function == ACPI_REGION_DEACTIVATE)
151     {
152         *RegionContext = NULL;
153     }
154     else
155     {
156         *RegionContext = HandlerContext;
157     }
158
159     return_ACPI_STATUS (AE_OK);
160 }
161
162
163 /*******************************************************************************
164  *
165  * FUNCTION:    AcpiEvPciConfigRegionSetup
166  *
167  * PARAMETERS:  Handle              - Region we are interested in
168  *              Function            - Start or stop
169  *              HandlerContext      - Address space handler context
170  *              RegionContext       - Region specific context
171  *
172  * RETURN:      Status
173  *
174  * DESCRIPTION: Setup a PCI_Config operation region
175  *
176  * MUTEX:       Assumes namespace is not locked
177  *
178  ******************************************************************************/
179
180 ACPI_STATUS
181 AcpiEvPciConfigRegionSetup (
182     ACPI_HANDLE             Handle,
183     UINT32                  Function,
184     void                    *HandlerContext,
185     void                    **RegionContext)
186 {
187     ACPI_STATUS             Status = AE_OK;
188     UINT64                  PciValue;
189     ACPI_PCI_ID             *PciId = *RegionContext;
190     ACPI_OPERAND_OBJECT     *HandlerObj;
191     ACPI_NAMESPACE_NODE     *ParentNode;
192     ACPI_NAMESPACE_NODE     *PciRootNode;
193     ACPI_NAMESPACE_NODE     *PciDeviceNode;
194     ACPI_OPERAND_OBJECT     *RegionObj = (ACPI_OPERAND_OBJECT  *) Handle;
195
196
197     ACPI_FUNCTION_TRACE (EvPciConfigRegionSetup);
198
199
200     HandlerObj = RegionObj->Region.Handler;
201     if (!HandlerObj)
202     {
203         /*
204          * No installed handler. This shouldn't happen because the dispatch
205          * routine checks before we get here, but we check again just in case.
206          */
207         ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
208             "Attempting to init a region %p, with no handler\n", RegionObj));
209         return_ACPI_STATUS (AE_NOT_EXIST);
210     }
211
212     *RegionContext = NULL;
213     if (Function == ACPI_REGION_DEACTIVATE)
214     {
215         if (PciId)
216         {
217             ACPI_FREE (PciId);
218         }
219         return_ACPI_STATUS (Status);
220     }
221
222     ParentNode = RegionObj->Region.Node->Parent;
223
224     /*
225      * Get the _SEG and _BBN values from the device upon which the handler
226      * is installed.
227      *
228      * We need to get the _SEG and _BBN objects relative to the PCI BUS device.
229      * This is the device the handler has been registered to handle.
230      */
231
232     /*
233      * If the AddressSpace.Node is still pointing to the root, we need
234      * to scan upward for a PCI Root bridge and re-associate the OpRegion
235      * handlers with that device.
236      */
237     if (HandlerObj->AddressSpace.Node == AcpiGbl_RootNode)
238     {
239         /* Start search from the parent object */
240
241         PciRootNode = ParentNode;
242         while (PciRootNode != AcpiGbl_RootNode)
243         {
244             /* Get the _HID/_CID in order to detect a RootBridge */
245
246             if (AcpiEvIsPciRootBridge (PciRootNode))
247             {
248                 /* Install a handler for this PCI root bridge */
249
250                 Status = AcpiInstallAddressSpaceHandler (
251                     (ACPI_HANDLE) PciRootNode,
252                     ACPI_ADR_SPACE_PCI_CONFIG,
253                     ACPI_DEFAULT_HANDLER, NULL, NULL);
254                 if (ACPI_FAILURE (Status))
255                 {
256                     if (Status == AE_SAME_HANDLER)
257                     {
258                         /*
259                          * It is OK if the handler is already installed on the
260                          * root bridge. Still need to return a context object
261                          * for the new PCI_Config operation region, however.
262                          */
263                         Status = AE_OK;
264                     }
265                     else
266                     {
267                         ACPI_EXCEPTION ((AE_INFO, Status,
268                             "Could not install PciConfig handler "
269                             "for Root Bridge %4.4s",
270                             AcpiUtGetNodeName (PciRootNode)));
271                     }
272                 }
273                 break;
274             }
275
276             PciRootNode = PciRootNode->Parent;
277         }
278
279         /* PCI root bridge not found, use namespace root node */
280     }
281     else
282     {
283         PciRootNode = HandlerObj->AddressSpace.Node;
284     }
285
286     /*
287      * If this region is now initialized, we are done.
288      * (InstallAddressSpaceHandler could have initialized it)
289      */
290     if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
291     {
292         return_ACPI_STATUS (AE_OK);
293     }
294
295     /* Region is still not initialized. Create a new context */
296
297     PciId = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PCI_ID));
298     if (!PciId)
299     {
300         return_ACPI_STATUS (AE_NO_MEMORY);
301     }
302
303     /*
304      * For PCI_Config space access, we need the segment, bus, device and
305      * function numbers. Acquire them here.
306      *
307      * Find the parent device object. (This allows the operation region to be
308      * within a subscope under the device, such as a control method.)
309      */
310     PciDeviceNode = RegionObj->Region.Node;
311     while (PciDeviceNode && (PciDeviceNode->Type != ACPI_TYPE_DEVICE))
312     {
313         PciDeviceNode = PciDeviceNode->Parent;
314     }
315
316     if (!PciDeviceNode)
317     {
318         ACPI_FREE (PciId);
319         return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
320     }
321
322     /*
323      * Get the PCI device and function numbers from the _ADR object
324      * contained in the parent's scope.
325      */
326     Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR,
327         PciDeviceNode, &PciValue);
328
329     /*
330      * The default is zero, and since the allocation above zeroed the data,
331      * just do nothing on failure.
332      */
333     if (ACPI_SUCCESS (Status))
334     {
335         PciId->Device   = ACPI_HIWORD (ACPI_LODWORD (PciValue));
336         PciId->Function = ACPI_LOWORD (ACPI_LODWORD (PciValue));
337     }
338
339     /* The PCI segment number comes from the _SEG method */
340
341     Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG,
342         PciRootNode, &PciValue);
343     if (ACPI_SUCCESS (Status))
344     {
345         PciId->Segment = ACPI_LOWORD (PciValue);
346     }
347
348     /* The PCI bus number comes from the _BBN method */
349
350     Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN,
351         PciRootNode, &PciValue);
352     if (ACPI_SUCCESS (Status))
353     {
354         PciId->Bus = ACPI_LOWORD (PciValue);
355     }
356
357     /* Complete/update the PCI ID for this device */
358
359     Status = AcpiHwDerivePciId (PciId, PciRootNode, RegionObj->Region.Node);
360     if (ACPI_FAILURE (Status))
361     {
362         ACPI_FREE (PciId);
363         return_ACPI_STATUS (Status);
364     }
365
366     *RegionContext = PciId;
367     return_ACPI_STATUS (AE_OK);
368 }
369
370
371 /*******************************************************************************
372  *
373  * FUNCTION:    AcpiEvIsPciRootBridge
374  *
375  * PARAMETERS:  Node            - Device node being examined
376  *
377  * RETURN:      TRUE if device is a PCI/PCI-Express Root Bridge
378  *
379  * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by
380  *              examining the _HID and _CID for the device.
381  *
382  ******************************************************************************/
383
384 static BOOLEAN
385 AcpiEvIsPciRootBridge (
386     ACPI_NAMESPACE_NODE     *Node)
387 {
388     ACPI_STATUS             Status;
389     ACPI_PNP_DEVICE_ID      *Hid;
390     ACPI_PNP_DEVICE_ID_LIST *Cid;
391     UINT32                  i;
392     BOOLEAN                 Match;
393
394
395     /* Get the _HID and check for a PCI Root Bridge */
396
397     Status = AcpiUtExecute_HID (Node, &Hid);
398     if (ACPI_FAILURE (Status))
399     {
400         return (FALSE);
401     }
402
403     Match = AcpiUtIsPciRootBridge (Hid->String);
404     ACPI_FREE (Hid);
405
406     if (Match)
407     {
408         return (TRUE);
409     }
410
411     /* The _HID did not match. Get the _CID and check for a PCI Root Bridge */
412
413     Status = AcpiUtExecute_CID (Node, &Cid);
414     if (ACPI_FAILURE (Status))
415     {
416         return (FALSE);
417     }
418
419     /* Check all _CIDs in the returned list */
420
421     for (i = 0; i < Cid->Count; i++)
422     {
423         if (AcpiUtIsPciRootBridge (Cid->Ids[i].String))
424         {
425             ACPI_FREE (Cid);
426             return (TRUE);
427         }
428     }
429
430     ACPI_FREE (Cid);
431     return (FALSE);
432 }
433
434
435 /*******************************************************************************
436  *
437  * FUNCTION:    AcpiEvPciBarRegionSetup
438  *
439  * PARAMETERS:  Handle              - Region we are interested in
440  *              Function            - Start or stop
441  *              HandlerContext      - Address space handler context
442  *              RegionContext       - Region specific context
443  *
444  * RETURN:      Status
445  *
446  * DESCRIPTION: Setup a PciBAR operation region
447  *
448  * MUTEX:       Assumes namespace is not locked
449  *
450  ******************************************************************************/
451
452 ACPI_STATUS
453 AcpiEvPciBarRegionSetup (
454     ACPI_HANDLE             Handle,
455     UINT32                  Function,
456     void                    *HandlerContext,
457     void                    **RegionContext)
458 {
459     ACPI_FUNCTION_TRACE (EvPciBarRegionSetup);
460
461
462     return_ACPI_STATUS (AE_OK);
463 }
464
465
466 /*******************************************************************************
467  *
468  * FUNCTION:    AcpiEvCmosRegionSetup
469  *
470  * PARAMETERS:  Handle              - Region we are interested in
471  *              Function            - Start or stop
472  *              HandlerContext      - Address space handler context
473  *              RegionContext       - Region specific context
474  *
475  * RETURN:      Status
476  *
477  * DESCRIPTION: Setup a CMOS operation region
478  *
479  * MUTEX:       Assumes namespace is not locked
480  *
481  ******************************************************************************/
482
483 ACPI_STATUS
484 AcpiEvCmosRegionSetup (
485     ACPI_HANDLE             Handle,
486     UINT32                  Function,
487     void                    *HandlerContext,
488     void                    **RegionContext)
489 {
490     ACPI_FUNCTION_TRACE (EvCmosRegionSetup);
491
492
493     return_ACPI_STATUS (AE_OK);
494 }
495
496
497 /*******************************************************************************
498  *
499  * FUNCTION:    AcpiEvDefaultRegionSetup
500  *
501  * PARAMETERS:  Handle              - Region we are interested in
502  *              Function            - Start or stop
503  *              HandlerContext      - Address space handler context
504  *              RegionContext       - Region specific context
505  *
506  * RETURN:      Status
507  *
508  * DESCRIPTION: Default region initialization
509  *
510  ******************************************************************************/
511
512 ACPI_STATUS
513 AcpiEvDefaultRegionSetup (
514     ACPI_HANDLE             Handle,
515     UINT32                  Function,
516     void                    *HandlerContext,
517     void                    **RegionContext)
518 {
519     ACPI_FUNCTION_TRACE (EvDefaultRegionSetup);
520
521
522     if (Function == ACPI_REGION_DEACTIVATE)
523     {
524         *RegionContext = NULL;
525     }
526     else
527     {
528         *RegionContext = HandlerContext;
529     }
530
531     return_ACPI_STATUS (AE_OK);
532 }
533
534
535 /*******************************************************************************
536  *
537  * FUNCTION:    AcpiEvInitializeRegion
538  *
539  * PARAMETERS:  RegionObj       - Region we are initializing
540  *              AcpiNsLocked    - Is namespace locked?
541  *
542  * RETURN:      Status
543  *
544  * DESCRIPTION: Initializes the region, finds any _REG methods and saves them
545  *              for execution at a later time
546  *
547  *              Get the appropriate address space handler for a newly
548  *              created region.
549  *
550  *              This also performs address space specific initialization. For
551  *              example, PCI regions must have an _ADR object that contains
552  *              a PCI address in the scope of the definition. This address is
553  *              required to perform an access to PCI config space.
554  *
555  * MUTEX:       Interpreter should be unlocked, because we may run the _REG
556  *              method for this region.
557  *
558  ******************************************************************************/
559
560 ACPI_STATUS
561 AcpiEvInitializeRegion (
562     ACPI_OPERAND_OBJECT     *RegionObj,
563     BOOLEAN                 AcpiNsLocked)
564 {
565     ACPI_OPERAND_OBJECT     *HandlerObj;
566     ACPI_OPERAND_OBJECT     *ObjDesc;
567     ACPI_ADR_SPACE_TYPE     SpaceId;
568     ACPI_NAMESPACE_NODE     *Node;
569     ACPI_STATUS             Status;
570
571
572     ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked);
573
574
575     if (!RegionObj)
576     {
577         return_ACPI_STATUS (AE_BAD_PARAMETER);
578     }
579
580     if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED)
581     {
582         return_ACPI_STATUS (AE_OK);
583     }
584
585     AcpiEvAssociateRegMethod (RegionObj);
586     RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED;
587
588     Node = RegionObj->Region.Node->Parent;
589     SpaceId = RegionObj->Region.SpaceId;
590
591     /*
592      * The following loop depends upon the root Node having no parent
593      * ie: AcpiGbl_RootNode->Parent being set to NULL
594      */
595     while (Node)
596     {
597         /* Check to see if a handler exists */
598
599         HandlerObj = NULL;
600         ObjDesc = AcpiNsGetAttachedObject (Node);
601         if (ObjDesc)
602         {
603             /* Can only be a handler if the object exists */
604
605             switch (Node->Type)
606             {
607             case ACPI_TYPE_DEVICE:
608             case ACPI_TYPE_PROCESSOR:
609             case ACPI_TYPE_THERMAL:
610
611                 HandlerObj = ObjDesc->CommonNotify.Handler;
612                 break;
613
614             case ACPI_TYPE_METHOD:
615                 /*
616                  * If we are executing module level code, the original
617                  * Node's object was replaced by this Method object and we
618                  * saved the handler in the method object.
619                  *
620                  * See AcpiNsExecModuleCode
621                  */
622                 if (ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)
623                 {
624                     HandlerObj = ObjDesc->Method.Dispatch.Handler;
625                 }
626                 break;
627
628             default:
629
630                 /* Ignore other objects */
631
632                 break;
633             }
634
635             HandlerObj = AcpiEvFindRegionHandler (SpaceId, HandlerObj);
636             if (HandlerObj)
637             {
638                 /* Found correct handler */
639
640                 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
641                     "Found handler %p for region %p in obj %p\n",
642                     HandlerObj, RegionObj, ObjDesc));
643
644                 Status = AcpiEvAttachRegion (HandlerObj, RegionObj,
645                     AcpiNsLocked);
646
647                 /*
648                  * Tell all users that this region is usable by
649                  * running the _REG method
650                  */
651                 if (AcpiNsLocked)
652                 {
653                     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
654                     if (ACPI_FAILURE (Status))
655                     {
656                         return_ACPI_STATUS (Status);
657                     }
658                 }
659
660                 Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT);
661
662                 if (AcpiNsLocked)
663                 {
664                     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
665                     if (ACPI_FAILURE (Status))
666                     {
667                         return_ACPI_STATUS (Status);
668                     }
669                 }
670
671                 return_ACPI_STATUS (AE_OK);
672             }
673         }
674
675         /* This node does not have the handler we need; Pop up one level */
676
677         Node = Node->Parent;
678     }
679
680     /* If we get here, there is no handler for this region */
681
682     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
683         "No handler for RegionType %s(%X) (RegionObj %p)\n",
684         AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj));
685
686     return_ACPI_STATUS (AE_NOT_EXIST);
687 }