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