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