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