Subversion Repositories Kolibri OS

Rev

Rev 1498 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1498 serge 1
/******************************************************************************
2
 *
3
 * Module Name: evxface - External interfaces for ACPI events
4
 *
5
 *****************************************************************************/
6
 
7
/******************************************************************************
8
 *
9
 * 1. Copyright Notice
10
 *
2216 Serge 11
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
1498 serge 12
 * All rights reserved.
13
 *
14
 * 2. License
15
 *
16
 * 2.1. This is your license from Intel Corp. under its intellectual property
17
 * rights.  You may have additional license terms from the party that provided
18
 * you this software, covering your right to use that party's intellectual
19
 * property rights.
20
 *
21
 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
 * copy of the source code appearing in this file ("Covered Code") an
23
 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
 * base code distributed originally by Intel ("Original Intel Code") to copy,
25
 * make derivatives, distribute, use and display any portion of the Covered
26
 * Code in any form, with the right to sublicense such rights; and
27
 *
28
 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
 * license (with the right to sublicense), under only those claims of Intel
30
 * patents that are infringed by the Original Intel Code, to make, use, sell,
31
 * offer to sell, and import the Covered Code and derivative works thereof
32
 * solely to the minimum extent necessary to exercise the above copyright
33
 * license, and in no event shall the patent license extend to any additions
34
 * to or modifications of the Original Intel Code.  No other license or right
35
 * is granted directly or by implication, estoppel or otherwise;
36
 *
37
 * The above copyright and patent license is granted only if the following
38
 * conditions are met:
39
 *
40
 * 3. Conditions
41
 *
42
 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
 * Redistribution of source code of any substantial portion of the Covered
44
 * Code or modification with rights to further distribute source must include
45
 * the above Copyright Notice, the above License, this list of Conditions,
46
 * and the following Disclaimer and Export Compliance provision.  In addition,
47
 * Licensee must cause all Covered Code to which Licensee contributes to
48
 * contain a file documenting the changes Licensee made to create that Covered
49
 * Code and the date of any change.  Licensee must include in that file the
50
 * documentation of any changes made by any predecessor Licensee.  Licensee
51
 * must include a prominent statement that the modification is derived,
52
 * directly or indirectly, from Original Intel Code.
53
 *
54
 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
 * Redistribution of source code of any substantial portion of the Covered
56
 * Code or modification without rights to further distribute source must
57
 * include the following Disclaimer and Export Compliance provision in the
58
 * documentation and/or other materials provided with distribution.  In
59
 * addition, Licensee may not authorize further sublicense of source of any
60
 * portion of the Covered Code, and must include terms to the effect that the
61
 * license from Licensee to its licensee is limited to the intellectual
62
 * property embodied in the software Licensee provides to its licensee, and
63
 * not to intellectual property embodied in modifications its licensee may
64
 * make.
65
 *
66
 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67
 * substantial portion of the Covered Code or modification must reproduce the
68
 * above Copyright Notice, and the following Disclaimer and Export Compliance
69
 * provision in the documentation and/or other materials provided with the
70
 * distribution.
71
 *
72
 * 3.4. Intel retains all right, title, and interest in and to the Original
73
 * Intel Code.
74
 *
75
 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
 * Intel shall be used in advertising or otherwise to promote the sale, use or
77
 * other dealings in products derived from or relating to the Covered Code
78
 * without prior written authorization from Intel.
79
 *
80
 * 4. Disclaimer and Export Compliance
81
 *
82
 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85
 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86
 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87
 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
 * PARTICULAR PURPOSE.
89
 *
90
 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96
 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
 * LIMITED REMEDY.
98
 *
99
 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100
 * software or system incorporating such software without first obtaining any
101
 * required license or other approval from the U. S. Department of Commerce or
102
 * any other agency or department of the United States Government.  In the
103
 * event Licensee exports any such software from the United States or
104
 * re-exports any such software from a foreign destination, Licensee shall
105
 * ensure that the distribution and export/re-export of the software is in
106
 * compliance with all laws, regulations, orders, or other restrictions of the
107
 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
 * any of its subsidiaries will export/re-export any technical data, process,
109
 * software, or service, directly or indirectly, to any country for which the
110
 * United States government or any agency thereof requires an export license,
111
 * other governmental approval, or letter of assurance, without first obtaining
112
 * such license, approval or letter.
113
 *
114
 *****************************************************************************/
115
 
116
 
117
#define __EVXFACE_C__
118
 
119
#include "acpi.h"
120
#include "accommon.h"
121
#include "acnamesp.h"
122
#include "acevents.h"
123
#include "acinterp.h"
124
 
125
#define _COMPONENT          ACPI_EVENTS
126
        ACPI_MODULE_NAME    ("evxface")
127
 
128
 
129
/*******************************************************************************
130
 *
131
 * FUNCTION:    AcpiInstallExceptionHandler
132
 *
133
 * PARAMETERS:  Handler         - Pointer to the handler function for the
134
 *                                event
135
 *
136
 * RETURN:      Status
137
 *
138
 * DESCRIPTION: Saves the pointer to the handler function
139
 *
140
 ******************************************************************************/
141
 
142
ACPI_STATUS
143
AcpiInstallExceptionHandler (
144
    ACPI_EXCEPTION_HANDLER  Handler)
145
{
146
    ACPI_STATUS             Status;
147
 
148
 
149
    ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
150
 
151
 
152
    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
153
    if (ACPI_FAILURE (Status))
154
    {
155
        return_ACPI_STATUS (Status);
156
    }
157
 
158
    /* Don't allow two handlers. */
159
 
160
    if (AcpiGbl_ExceptionHandler)
161
    {
162
        Status = AE_ALREADY_EXISTS;
163
        goto Cleanup;
164
    }
165
 
166
    /* Install the handler */
167
 
168
    AcpiGbl_ExceptionHandler = Handler;
169
 
170
Cleanup:
171
    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
172
    return_ACPI_STATUS (Status);
173
}
174
 
175
ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
176
 
177
 
178
/*******************************************************************************
179
 *
2216 Serge 180
 * FUNCTION:    AcpiInstallGlobalEventHandler
181
 *
182
 * PARAMETERS:  Handler         - Pointer to the global event handler function
183
 *              Context         - Value passed to the handler on each event
184
 *
185
 * RETURN:      Status
186
 *
187
 * DESCRIPTION: Saves the pointer to the handler function. The global handler
188
 *              is invoked upon each incoming GPE and Fixed Event. It is
189
 *              invoked at interrupt level at the time of the event dispatch.
190
 *              Can be used to update event counters, etc.
191
 *
192
 ******************************************************************************/
193
 
194
ACPI_STATUS
195
AcpiInstallGlobalEventHandler (
196
    ACPI_GBL_EVENT_HANDLER  Handler,
197
    void                    *Context)
198
{
199
    ACPI_STATUS             Status;
200
 
201
 
202
    ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
203
 
204
 
205
    /* Parameter validation */
206
 
207
    if (!Handler)
208
    {
209
        return_ACPI_STATUS (AE_BAD_PARAMETER);
210
    }
211
 
212
    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
213
    if (ACPI_FAILURE (Status))
214
    {
215
        return_ACPI_STATUS (Status);
216
    }
217
 
218
    /* Don't allow two handlers. */
219
 
220
    if (AcpiGbl_GlobalEventHandler)
221
    {
222
        Status = AE_ALREADY_EXISTS;
223
        goto Cleanup;
224
    }
225
 
226
    AcpiGbl_GlobalEventHandler = Handler;
227
    AcpiGbl_GlobalEventHandlerContext = Context;
228
 
229
 
230
Cleanup:
231
    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
232
    return_ACPI_STATUS (Status);
233
}
234
 
235
ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
236
 
237
 
238
/*******************************************************************************
239
 *
1498 serge 240
 * FUNCTION:    AcpiInstallFixedEventHandler
241
 *
242
 * PARAMETERS:  Event           - Event type to enable.
243
 *              Handler         - Pointer to the handler function for the
244
 *                                event
245
 *              Context         - Value passed to the handler on each GPE
246
 *
247
 * RETURN:      Status
248
 *
249
 * DESCRIPTION: Saves the pointer to the handler function and then enables the
250
 *              event.
251
 *
252
 ******************************************************************************/
253
 
254
ACPI_STATUS
255
AcpiInstallFixedEventHandler (
256
    UINT32                  Event,
257
    ACPI_EVENT_HANDLER      Handler,
258
    void                    *Context)
259
{
260
    ACPI_STATUS             Status;
261
 
262
 
263
    ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
264
 
265
 
266
    /* Parameter validation */
267
 
268
    if (Event > ACPI_EVENT_MAX)
269
    {
270
        return_ACPI_STATUS (AE_BAD_PARAMETER);
271
    }
272
 
273
    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
274
    if (ACPI_FAILURE (Status))
275
    {
276
        return_ACPI_STATUS (Status);
277
    }
278
 
279
    /* Don't allow two handlers. */
280
 
281
    if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
282
    {
283
        Status = AE_ALREADY_EXISTS;
284
        goto Cleanup;
285
    }
286
 
287
    /* Install the handler before enabling the event */
288
 
289
    AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
290
    AcpiGbl_FixedEventHandlers[Event].Context = Context;
291
 
292
    Status = AcpiEnableEvent (Event, 0);
293
    if (ACPI_FAILURE (Status))
294
    {
295
        ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event));
296
 
297
        /* Remove the handler */
298
 
299
        AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
300
        AcpiGbl_FixedEventHandlers[Event].Context = NULL;
301
    }
302
    else
303
    {
304
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
305
            "Enabled fixed event %X, Handler=%p\n", Event, Handler));
306
    }
307
 
308
 
309
Cleanup:
310
    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
311
    return_ACPI_STATUS (Status);
312
}
313
 
314
ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
315
 
316
 
317
/*******************************************************************************
318
 *
319
 * FUNCTION:    AcpiRemoveFixedEventHandler
320
 *
321
 * PARAMETERS:  Event           - Event type to disable.
322
 *              Handler         - Address of the handler
323
 *
324
 * RETURN:      Status
325
 *
326
 * DESCRIPTION: Disables the event and unregisters the event handler.
327
 *
328
 ******************************************************************************/
329
 
330
ACPI_STATUS
331
AcpiRemoveFixedEventHandler (
332
    UINT32                  Event,
333
    ACPI_EVENT_HANDLER      Handler)
334
{
335
    ACPI_STATUS             Status = AE_OK;
336
 
337
 
338
    ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
339
 
340
 
341
    /* Parameter validation */
342
 
343
    if (Event > ACPI_EVENT_MAX)
344
    {
345
        return_ACPI_STATUS (AE_BAD_PARAMETER);
346
    }
347
 
348
    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
349
    if (ACPI_FAILURE (Status))
350
    {
351
        return_ACPI_STATUS (Status);
352
    }
353
 
354
    /* Disable the event before removing the handler */
355
 
356
    Status = AcpiDisableEvent (Event, 0);
357
 
358
    /* Always Remove the handler */
359
 
360
    AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
361
    AcpiGbl_FixedEventHandlers[Event].Context = NULL;
362
 
363
    if (ACPI_FAILURE (Status))
364
    {
365
        ACPI_WARNING ((AE_INFO,
366
            "Could not write to fixed event enable register 0x%X", Event));
367
    }
368
    else
369
    {
370
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event));
371
    }
372
 
373
    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
374
    return_ACPI_STATUS (Status);
375
}
376
 
377
ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
378
 
379
 
380
/*******************************************************************************
381
 *
382
 * FUNCTION:    AcpiInstallNotifyHandler
383
 *
384
 * PARAMETERS:  Device          - The device for which notifies will be handled
385
 *              HandlerType     - The type of handler:
386
 *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
387
 *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
388
 *                                  ACPI_ALL_NOTIFY:  both system and device
389
 *              Handler         - Address of the handler
390
 *              Context         - Value passed to the handler on each GPE
391
 *
392
 * RETURN:      Status
393
 *
394
 * DESCRIPTION: Install a handler for notifies on an ACPI device
395
 *
396
 ******************************************************************************/
397
 
398
ACPI_STATUS
399
AcpiInstallNotifyHandler (
400
    ACPI_HANDLE             Device,
401
    UINT32                  HandlerType,
402
    ACPI_NOTIFY_HANDLER     Handler,
403
    void                    *Context)
404
{
405
    ACPI_OPERAND_OBJECT     *ObjDesc;
406
    ACPI_OPERAND_OBJECT     *NotifyObj;
407
    ACPI_NAMESPACE_NODE     *Node;
408
    ACPI_STATUS             Status;
409
 
410
 
411
    ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
412
 
413
 
414
    /* Parameter validation */
415
 
416
    if ((!Device)  ||
417
        (!Handler) ||
418
        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
419
    {
420
        return_ACPI_STATUS (AE_BAD_PARAMETER);
421
    }
422
 
423
    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
424
    if (ACPI_FAILURE (Status))
425
    {
426
        return_ACPI_STATUS (Status);
427
    }
428
 
429
    /* Convert and validate the device handle */
430
 
431
    Node = AcpiNsValidateHandle (Device);
432
    if (!Node)
433
    {
434
        Status = AE_BAD_PARAMETER;
435
        goto UnlockAndExit;
436
    }
437
 
438
    /*
439
     * Root Object:
440
     * Registering a notify handler on the root object indicates that the
441
     * caller wishes to receive notifications for all objects. Note that
442
     * only one  global handler can be regsitered (per notify type).
443
     */
444
    if (Device == ACPI_ROOT_OBJECT)
445
    {
446
        /* Make sure the handler is not already installed */
447
 
448
        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
449
                AcpiGbl_SystemNotify.Handler)       ||
450
            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
451
                AcpiGbl_DeviceNotify.Handler))
452
        {
453
            Status = AE_ALREADY_EXISTS;
454
            goto UnlockAndExit;
455
        }
456
 
457
        if (HandlerType & ACPI_SYSTEM_NOTIFY)
458
        {
459
            AcpiGbl_SystemNotify.Node    = Node;
460
            AcpiGbl_SystemNotify.Handler = Handler;
461
            AcpiGbl_SystemNotify.Context = Context;
462
        }
463
 
464
        if (HandlerType & ACPI_DEVICE_NOTIFY)
465
        {
466
            AcpiGbl_DeviceNotify.Node    = Node;
467
            AcpiGbl_DeviceNotify.Handler = Handler;
468
            AcpiGbl_DeviceNotify.Context = Context;
469
        }
470
 
471
        /* Global notify handler installed */
472
    }
473
 
474
    /*
475
     * All Other Objects:
476
     * Caller will only receive notifications specific to the target object.
477
     * Note that only certain object types can receive notifications.
478
     */
479
    else
480
    {
481
        /* Notifies allowed on this object? */
482
 
483
        if (!AcpiEvIsNotifyObject (Node))
484
        {
485
            Status = AE_TYPE;
486
            goto UnlockAndExit;
487
        }
488
 
489
        /* Check for an existing internal object */
490
 
491
        ObjDesc = AcpiNsGetAttachedObject (Node);
492
        if (ObjDesc)
493
        {
494
            /* Object exists - make sure there's no handler */
495
 
496
            if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
497
                    ObjDesc->CommonNotify.SystemNotify)   ||
498
                ((HandlerType & ACPI_DEVICE_NOTIFY) &&
499
                    ObjDesc->CommonNotify.DeviceNotify))
500
            {
501
                Status = AE_ALREADY_EXISTS;
502
                goto UnlockAndExit;
503
            }
504
        }
505
        else
506
        {
507
            /* Create a new object */
508
 
509
            ObjDesc = AcpiUtCreateInternalObject (Node->Type);
510
            if (!ObjDesc)
511
            {
512
                Status = AE_NO_MEMORY;
513
                goto UnlockAndExit;
514
            }
515
 
516
            /* Attach new object to the Node */
517
 
518
            Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
519
 
520
            /* Remove local reference to the object */
521
 
522
            AcpiUtRemoveReference (ObjDesc);
523
            if (ACPI_FAILURE (Status))
524
            {
525
                goto UnlockAndExit;
526
            }
527
        }
528
 
529
        /* Install the handler */
530
 
531
        NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
532
        if (!NotifyObj)
533
        {
534
            Status = AE_NO_MEMORY;
535
            goto UnlockAndExit;
536
        }
537
 
538
        NotifyObj->Notify.Node    = Node;
539
        NotifyObj->Notify.Handler = Handler;
540
        NotifyObj->Notify.Context = Context;
541
 
542
        if (HandlerType & ACPI_SYSTEM_NOTIFY)
543
        {
544
            ObjDesc->CommonNotify.SystemNotify = NotifyObj;
545
        }
546
 
547
        if (HandlerType & ACPI_DEVICE_NOTIFY)
548
        {
549
            ObjDesc->CommonNotify.DeviceNotify = NotifyObj;
550
        }
551
 
552
        if (HandlerType == ACPI_ALL_NOTIFY)
553
        {
554
            /* Extra ref if installed in both */
555
 
556
            AcpiUtAddReference (NotifyObj);
557
        }
558
    }
559
 
560
 
561
UnlockAndExit:
562
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
563
    return_ACPI_STATUS (Status);
564
}
565
 
566
ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
567
 
568
 
569
/*******************************************************************************
570
 *
571
 * FUNCTION:    AcpiRemoveNotifyHandler
572
 *
573
 * PARAMETERS:  Device          - The device for which notifies will be handled
574
 *              HandlerType     - The type of handler:
575
 *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
576
 *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
577
 *                                  ACPI_ALL_NOTIFY:  both system and device
578
 *              Handler         - Address of the handler
579
 *
580
 * RETURN:      Status
581
 *
582
 * DESCRIPTION: Remove a handler for notifies on an ACPI device
583
 *
584
 ******************************************************************************/
585
 
586
ACPI_STATUS
587
AcpiRemoveNotifyHandler (
588
    ACPI_HANDLE             Device,
589
    UINT32                  HandlerType,
590
    ACPI_NOTIFY_HANDLER     Handler)
591
{
592
    ACPI_OPERAND_OBJECT     *NotifyObj;
593
    ACPI_OPERAND_OBJECT     *ObjDesc;
594
    ACPI_NAMESPACE_NODE     *Node;
595
    ACPI_STATUS             Status;
596
 
597
 
598
    ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
599
 
600
 
601
    /* Parameter validation */
602
 
603
    if ((!Device)  ||
604
        (!Handler) ||
605
        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
606
    {
607
        return_ACPI_STATUS (AE_BAD_PARAMETER);
608
    }
609
 
610
    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
611
    if (ACPI_FAILURE (Status))
612
    {
613
        return_ACPI_STATUS (Status);
614
    }
615
 
616
    /* Convert and validate the device handle */
617
 
618
    Node = AcpiNsValidateHandle (Device);
619
    if (!Node)
620
    {
621
        Status = AE_BAD_PARAMETER;
622
        goto UnlockAndExit;
623
    }
624
 
625
    /* Root Object */
626
 
627
    if (Device == ACPI_ROOT_OBJECT)
628
    {
629
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
630
            "Removing notify handler for namespace root object\n"));
631
 
632
        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
633
              !AcpiGbl_SystemNotify.Handler)        ||
634
            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
635
              !AcpiGbl_DeviceNotify.Handler))
636
        {
637
            Status = AE_NOT_EXIST;
638
            goto UnlockAndExit;
639
        }
640
 
641
        if (HandlerType & ACPI_SYSTEM_NOTIFY)
642
        {
643
            AcpiGbl_SystemNotify.Node    = NULL;
644
            AcpiGbl_SystemNotify.Handler = NULL;
645
            AcpiGbl_SystemNotify.Context = NULL;
646
        }
647
 
648
        if (HandlerType & ACPI_DEVICE_NOTIFY)
649
        {
650
            AcpiGbl_DeviceNotify.Node    = NULL;
651
            AcpiGbl_DeviceNotify.Handler = NULL;
652
            AcpiGbl_DeviceNotify.Context = NULL;
653
        }
654
    }
655
 
656
    /* All Other Objects */
657
 
658
    else
659
    {
660
        /* Notifies allowed on this object? */
661
 
662
        if (!AcpiEvIsNotifyObject (Node))
663
        {
664
            Status = AE_TYPE;
665
            goto UnlockAndExit;
666
        }
667
 
668
        /* Check for an existing internal object */
669
 
670
        ObjDesc = AcpiNsGetAttachedObject (Node);
671
        if (!ObjDesc)
672
        {
673
            Status = AE_NOT_EXIST;
674
            goto UnlockAndExit;
675
        }
676
 
677
        /* Object exists - make sure there's an existing handler */
678
 
679
        if (HandlerType & ACPI_SYSTEM_NOTIFY)
680
        {
681
            NotifyObj = ObjDesc->CommonNotify.SystemNotify;
682
            if (!NotifyObj)
683
            {
684
                Status = AE_NOT_EXIST;
685
                goto UnlockAndExit;
686
            }
687
 
688
            if (NotifyObj->Notify.Handler != Handler)
689
            {
690
                Status = AE_BAD_PARAMETER;
691
                goto UnlockAndExit;
692
            }
693
 
694
            /* Remove the handler */
695
 
696
            ObjDesc->CommonNotify.SystemNotify = NULL;
697
            AcpiUtRemoveReference (NotifyObj);
698
        }
699
 
700
        if (HandlerType & ACPI_DEVICE_NOTIFY)
701
        {
702
            NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
703
            if (!NotifyObj)
704
            {
705
                Status = AE_NOT_EXIST;
706
                goto UnlockAndExit;
707
            }
708
 
709
            if (NotifyObj->Notify.Handler != Handler)
710
            {
711
                Status = AE_BAD_PARAMETER;
712
                goto UnlockAndExit;
713
            }
714
 
715
            /* Remove the handler */
716
 
717
            ObjDesc->CommonNotify.DeviceNotify = NULL;
718
            AcpiUtRemoveReference (NotifyObj);
719
        }
720
    }
721
 
722
 
723
UnlockAndExit:
724
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
725
    return_ACPI_STATUS (Status);
726
}
727
 
728
ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
729
 
730
 
731
/*******************************************************************************
732
 *
733
 * FUNCTION:    AcpiInstallGpeHandler
734
 *
735
 * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
736
 *                                defined GPEs)
737
 *              GpeNumber       - The GPE number within the GPE block
738
 *              Type            - Whether this GPE should be treated as an
739
 *                                edge- or level-triggered interrupt.
740
 *              Address         - Address of the handler
741
 *              Context         - Value passed to the handler on each GPE
742
 *
743
 * RETURN:      Status
744
 *
745
 * DESCRIPTION: Install a handler for a General Purpose Event.
746
 *
747
 ******************************************************************************/
748
 
749
ACPI_STATUS
750
AcpiInstallGpeHandler (
751
    ACPI_HANDLE             GpeDevice,
752
    UINT32                  GpeNumber,
753
    UINT32                  Type,
2216 Serge 754
    ACPI_GPE_HANDLER        Address,
1498 serge 755
    void                    *Context)
756
{
757
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
2216 Serge 758
    ACPI_GPE_HANDLER_INFO   *Handler;
1498 serge 759
    ACPI_STATUS             Status;
760
    ACPI_CPU_FLAGS          Flags;
761
 
762
 
763
    ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
764
 
765
 
766
    /* Parameter validation */
767
 
768
    if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
769
    {
770
        return_ACPI_STATUS (AE_BAD_PARAMETER);
771
    }
772
 
773
    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
774
    if (ACPI_FAILURE (Status))
775
    {
776
        return_ACPI_STATUS (Status);
777
    }
778
 
2216 Serge 779
    /* Allocate and init handler object (before lock) */
780
 
781
    Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
782
    if (!Handler)
783
    {
784
        Status = AE_NO_MEMORY;
785
        goto UnlockAndExit;
786
    }
787
 
788
    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
789
 
1498 serge 790
    /* Ensure that we have a valid GPE number */
791
 
792
    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
793
    if (!GpeEventInfo)
794
    {
795
        Status = AE_BAD_PARAMETER;
2216 Serge 796
        goto FreeAndExit;
1498 serge 797
    }
798
 
799
    /* Make sure that there isn't a handler there already */
800
 
801
    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
802
            ACPI_GPE_DISPATCH_HANDLER)
803
    {
804
        Status = AE_ALREADY_EXISTS;
2216 Serge 805
        goto FreeAndExit;
1498 serge 806
    }
807
 
2216 Serge 808
    Handler->Address = Address;
809
    Handler->Context = Context;
810
    Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
811
    Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
812
        (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
1498 serge 813
 
2216 Serge 814
    /*
815
     * If the GPE is associated with a method, it may have been enabled
816
     * automatically during initialization, in which case it has to be
817
     * disabled now to avoid spurious execution of the handler.
818
     */
819
    if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
820
         (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
821
        GpeEventInfo->RuntimeCount)
1498 serge 822
    {
2216 Serge 823
        Handler->OriginallyEnabled = TRUE;
824
        (void) AcpiEvRemoveGpeReference (GpeEventInfo);
1498 serge 825
 
2216 Serge 826
        /* Sanity check of original type against new type */
1498 serge 827
 
2216 Serge 828
        if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
829
        {
830
            ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
831
        }
1498 serge 832
    }
833
 
834
    /* Install the handler */
835
 
836
    GpeEventInfo->Dispatch.Handler = Handler;
837
 
2216 Serge 838
    /* Setup up dispatch flags to indicate handler (vs. method/notify) */
1498 serge 839
 
840
    GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
841
    GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
842
 
843
    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
844
 
845
 
846
UnlockAndExit:
847
    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
848
    return_ACPI_STATUS (Status);
2216 Serge 849
 
850
FreeAndExit:
851
    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
852
    ACPI_FREE (Handler);
853
    goto UnlockAndExit;
1498 serge 854
}
855
 
856
ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
857
 
858
 
859
/*******************************************************************************
860
 *
861
 * FUNCTION:    AcpiRemoveGpeHandler
862
 *
863
 * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
864
 *                                defined GPEs)
865
 *              GpeNumber       - The event to remove a handler
866
 *              Address         - Address of the handler
867
 *
868
 * RETURN:      Status
869
 *
870
 * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
871
 *
872
 ******************************************************************************/
873
 
874
ACPI_STATUS
875
AcpiRemoveGpeHandler (
876
    ACPI_HANDLE             GpeDevice,
877
    UINT32                  GpeNumber,
2216 Serge 878
    ACPI_GPE_HANDLER        Address)
1498 serge 879
{
880
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
2216 Serge 881
    ACPI_GPE_HANDLER_INFO   *Handler;
1498 serge 882
    ACPI_STATUS             Status;
883
    ACPI_CPU_FLAGS          Flags;
884
 
885
 
886
    ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
887
 
888
 
889
    /* Parameter validation */
890
 
891
    if (!Address)
892
    {
893
        return_ACPI_STATUS (AE_BAD_PARAMETER);
894
    }
895
 
896
    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
897
    if (ACPI_FAILURE (Status))
898
    {
899
        return_ACPI_STATUS (Status);
900
    }
901
 
2216 Serge 902
    Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
903
 
1498 serge 904
    /* Ensure that we have a valid GPE number */
905
 
906
    GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
907
    if (!GpeEventInfo)
908
    {
909
        Status = AE_BAD_PARAMETER;
910
        goto UnlockAndExit;
911
    }
912
 
913
    /* Make sure that a handler is indeed installed */
914
 
915
    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
916
            ACPI_GPE_DISPATCH_HANDLER)
917
    {
918
        Status = AE_NOT_EXIST;
919
        goto UnlockAndExit;
920
    }
921
 
922
    /* Make sure that the installed handler is the same */
923
 
924
    if (GpeEventInfo->Dispatch.Handler->Address != Address)
925
    {
926
        Status = AE_BAD_PARAMETER;
927
        goto UnlockAndExit;
928
    }
929
 
930
    /* Remove the handler */
931
 
932
    Handler = GpeEventInfo->Dispatch.Handler;
933
 
934
    /* Restore Method node (if any), set dispatch flags */
935
 
936
    GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
2216 Serge 937
    GpeEventInfo->Flags &=
938
        ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
939
    GpeEventInfo->Flags |= Handler->OriginalFlags;
940
 
941
    /*
942
     * If the GPE was previously associated with a method and it was
943
     * enabled, it should be enabled at this point to restore the
944
     * post-initialization configuration.
945
     */
946
    if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
947
        Handler->OriginallyEnabled)
1498 serge 948
    {
2216 Serge 949
        (void) AcpiEvAddGpeReference (GpeEventInfo);
1498 serge 950
    }
951
 
952
    /* Now we can free the handler object */
953
 
954
    ACPI_FREE (Handler);
955
 
956
 
957
UnlockAndExit:
2216 Serge 958
    AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
1498 serge 959
    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
960
    return_ACPI_STATUS (Status);
961
}
962
 
963
ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
964
 
965
 
966
/*******************************************************************************
967
 *
968
 * FUNCTION:    AcpiAcquireGlobalLock
969
 *
970
 * PARAMETERS:  Timeout         - How long the caller is willing to wait
971
 *              Handle          - Where the handle to the lock is returned
972
 *                                (if acquired)
973
 *
974
 * RETURN:      Status
975
 *
976
 * DESCRIPTION: Acquire the ACPI Global Lock
977
 *
978
 * Note: Allows callers with the same thread ID to acquire the global lock
979
 * multiple times. In other words, externally, the behavior of the global lock
980
 * is identical to an AML mutex. On the first acquire, a new handle is
981
 * returned. On any subsequent calls to acquire by the same thread, the same
982
 * handle is returned.
983
 *
984
 ******************************************************************************/
985
 
986
ACPI_STATUS
987
AcpiAcquireGlobalLock (
988
    UINT16                  Timeout,
989
    UINT32                  *Handle)
990
{
991
    ACPI_STATUS             Status;
992
 
993
 
994
    if (!Handle)
995
    {
996
        return (AE_BAD_PARAMETER);
997
    }
998
 
999
    /* Must lock interpreter to prevent race conditions */
1000
 
1001
    AcpiExEnterInterpreter ();
1002
 
1003
    Status = AcpiExAcquireMutexObject (Timeout,
1004
                AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
1005
 
1006
    if (ACPI_SUCCESS (Status))
1007
    {
1008
        /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
1009
 
1010
        *Handle = AcpiGbl_GlobalLockHandle;
1011
    }
1012
 
1013
    AcpiExExitInterpreter ();
1014
    return (Status);
1015
}
1016
 
1017
ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
1018
 
1019
 
1020
/*******************************************************************************
1021
 *
1022
 * FUNCTION:    AcpiReleaseGlobalLock
1023
 *
1024
 * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
1025
 *
1026
 * RETURN:      Status
1027
 *
1028
 * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
1029
 *
1030
 ******************************************************************************/
1031
 
1032
ACPI_STATUS
1033
AcpiReleaseGlobalLock (
1034
    UINT32                  Handle)
1035
{
1036
    ACPI_STATUS             Status;
1037
 
1038
 
1039
    if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
1040
    {
1041
        return (AE_NOT_ACQUIRED);
1042
    }
1043
 
1044
    Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
1045
    return (Status);
1046
}
1047
 
1048
ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
1049