]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/evevent.c
Vendor import of the Intel ACPI CA 20021118 drop.
[FreeBSD/FreeBSD.git] / sys / contrib / dev / acpica / evevent.c
1 /******************************************************************************
2  *
3  * Module Name: evevent - Fixed and General Purpose Even handling and dispatch
4  *              $Revision: 96 $
5  *
6  *****************************************************************************/
7
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2002, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116
117 #include "acpi.h"
118 #include "acevents.h"
119 #include "acnamesp.h"
120
121 #define _COMPONENT          ACPI_EVENTS
122         ACPI_MODULE_NAME    ("evevent")
123
124
125 /*******************************************************************************
126  *
127  * FUNCTION:    AcpiEvInitialize
128  *
129  * PARAMETERS:  None
130  *
131  * RETURN:      Status
132  *
133  * DESCRIPTION: Initialize global data structures for events.
134  *
135  ******************************************************************************/
136
137 ACPI_STATUS
138 AcpiEvInitialize (
139     void)
140 {
141     ACPI_STATUS             Status;
142
143
144     ACPI_FUNCTION_TRACE ("EvInitialize");
145
146
147     /* Make sure we have ACPI tables */
148
149     if (!AcpiGbl_DSDT)
150     {
151         ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No ACPI tables present!\n"));
152         return_ACPI_STATUS (AE_NO_ACPI_TABLES);
153     }
154
155     /*
156      * Initialize the Fixed and General Purpose AcpiEvents prior.  This is
157      * done prior to enabling SCIs to prevent interrupts from occuring
158      * before handers are installed.
159      */
160     Status = AcpiEvFixedEventInitialize ();
161     if (ACPI_FAILURE (Status))
162     {
163         ACPI_DEBUG_PRINT ((ACPI_DB_FATAL,
164                 "Unable to initialize fixed events, %s\n",
165                 AcpiFormatException (Status)));
166         return_ACPI_STATUS (Status);
167     }
168
169     Status = AcpiEvGpeInitialize ();
170     if (ACPI_FAILURE (Status))
171     {
172         ACPI_DEBUG_PRINT ((ACPI_DB_FATAL,
173                 "Unable to initialize general purpose events, %s\n",
174                 AcpiFormatException (Status)));
175         return_ACPI_STATUS (Status);
176     }
177
178     return_ACPI_STATUS (Status);
179 }
180
181
182 /*******************************************************************************
183  *
184  * FUNCTION:    AcpiEvHandlerInitialize
185  *
186  * PARAMETERS:  None
187  *
188  * RETURN:      Status
189  *
190  * DESCRIPTION: Install handlers for the SCI, Global Lock, and GPEs.
191  *
192  ******************************************************************************/
193
194 ACPI_STATUS
195 AcpiEvHandlerInitialize (
196     void)
197 {
198     ACPI_STATUS             Status;
199
200
201     ACPI_FUNCTION_TRACE ("EvHandlerInitialize");
202
203
204     /* Install the SCI handler */
205
206     Status = AcpiEvInstallSciHandler ();
207     if (ACPI_FAILURE (Status))
208     {
209         ACPI_DEBUG_PRINT ((ACPI_DB_FATAL,
210                 "Unable to install System Control Interrupt Handler, %s\n",
211                 AcpiFormatException (Status)));
212         return_ACPI_STATUS (Status);
213     }
214
215     /* Install handlers for control method GPE handlers (_Lxx, _Exx) */
216
217     Status = AcpiEvInitGpeControlMethods ();
218     if (ACPI_FAILURE (Status))
219     {
220         ACPI_DEBUG_PRINT ((ACPI_DB_FATAL,
221                 "Unable to initialize GPE control methods, %s\n",
222                 AcpiFormatException (Status)));
223         return_ACPI_STATUS (Status);
224     }
225
226     /* Install the handler for the Global Lock */
227
228     Status = AcpiEvInitGlobalLockHandler ();
229     if (ACPI_FAILURE (Status))
230     {
231         ACPI_DEBUG_PRINT ((ACPI_DB_FATAL,
232                 "Unable to initialize Global Lock handler, %s\n",
233                 AcpiFormatException (Status)));
234         return_ACPI_STATUS (Status);
235     }
236
237     AcpiGbl_EventsInitialized = TRUE;
238     return_ACPI_STATUS (Status);
239 }
240
241
242 /*******************************************************************************
243  *
244  * FUNCTION:    AcpiEvFixedEventInitialize
245  *
246  * PARAMETERS:  None
247  *
248  * RETURN:      Status
249  *
250  * DESCRIPTION: Install the fixed event handlers and enable the fixed events.
251  *
252  ******************************************************************************/
253
254 ACPI_STATUS
255 AcpiEvFixedEventInitialize (
256     void)
257 {
258     NATIVE_UINT             i;
259     ACPI_STATUS             Status;
260
261
262     /*
263      * Initialize the structure that keeps track of fixed event handlers
264      * and enable the fixed events.
265      */
266     for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
267     {
268         AcpiGbl_FixedEventHandlers[i].Handler = NULL;
269         AcpiGbl_FixedEventHandlers[i].Context = NULL;
270
271         /* Enable the fixed event */
272
273         if (AcpiGbl_FixedEventInfo[i].EnableRegisterId != 0xFF)
274         {
275             Status = AcpiSetRegister (AcpiGbl_FixedEventInfo[i].EnableRegisterId,
276                                     0, ACPI_MTX_LOCK);
277             if (ACPI_FAILURE (Status))
278             {
279                 return (Status);
280             }
281         }
282     }
283
284     return (AE_OK);
285 }
286
287
288 /*******************************************************************************
289  *
290  * FUNCTION:    AcpiEvFixedEventDetect
291  *
292  * PARAMETERS:  None
293  *
294  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
295  *
296  * DESCRIPTION: Checks the PM status register for fixed events
297  *
298  ******************************************************************************/
299
300 UINT32
301 AcpiEvFixedEventDetect (
302     void)
303 {
304     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
305     UINT32                  FixedStatus;
306     UINT32                  FixedEnable;
307     NATIVE_UINT_MAX32       i;
308
309
310     ACPI_FUNCTION_NAME ("EvFixedEventDetect");
311
312
313     /*
314      * Read the fixed feature status and enable registers, as all the cases
315      * depend on their values.  Ignore errors here.
316      */
317     (void) AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, &FixedStatus);
318     (void) AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE, &FixedEnable);
319
320     ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
321         "Fixed AcpiEvent Block: Enable %08X Status %08X\n",
322         FixedEnable, FixedStatus));
323
324     /*
325      * Check for all possible Fixed Events and dispatch those that are active
326      */
327     for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
328     {
329         /* Both the status and enable bits must be on for this event */
330
331         if ((FixedStatus & AcpiGbl_FixedEventInfo[i].StatusBitMask) &&
332             (FixedEnable & AcpiGbl_FixedEventInfo[i].EnableBitMask))
333         {
334             /* Found an active (signalled) event */
335
336             IntStatus |= AcpiEvFixedEventDispatch (i);
337         }
338     }
339
340     return (IntStatus);
341 }
342
343
344 /*******************************************************************************
345  *
346  * FUNCTION:    AcpiEvFixedEventDispatch
347  *
348  * PARAMETERS:  Event               - Event type
349  *
350  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
351  *
352  * DESCRIPTION: Clears the status bit for the requested event, calls the
353  *              handler that previously registered for the event.
354  *
355  ******************************************************************************/
356
357 UINT32
358 AcpiEvFixedEventDispatch (
359     UINT32                  Event)
360 {
361
362
363     ACPI_FUNCTION_ENTRY ();
364
365
366     /* Clear the status bit */
367
368     (void) AcpiSetRegister (AcpiGbl_FixedEventInfo[Event].StatusRegisterId,
369                 1, ACPI_MTX_DO_NOT_LOCK);
370
371     /*
372      * Make sure we've got a handler.  If not, report an error.
373      * The event is disabled to prevent further interrupts.
374      */
375     if (NULL == AcpiGbl_FixedEventHandlers[Event].Handler)
376     {
377         (void) AcpiSetRegister (AcpiGbl_FixedEventInfo[Event].EnableRegisterId,
378                 0, ACPI_MTX_DO_NOT_LOCK);
379
380         ACPI_REPORT_ERROR (
381             ("EvGpeDispatch: No installed handler for fixed event [%08X]\n",
382             Event));
383
384         return (ACPI_INTERRUPT_NOT_HANDLED);
385     }
386
387     /* Invoke the Fixed Event handler */
388
389     return ((AcpiGbl_FixedEventHandlers[Event].Handler)(
390                                 AcpiGbl_FixedEventHandlers[Event].Context));
391 }
392
393
394 /*******************************************************************************
395  *
396  * FUNCTION:    AcpiEvGpeInitialize
397  *
398  * PARAMETERS:  None
399  *
400  * RETURN:      Status
401  *
402  * DESCRIPTION: Initialize the GPE data structures
403  *
404  ******************************************************************************/
405
406 ACPI_STATUS
407 AcpiEvGpeInitialize (void)
408 {
409     NATIVE_UINT_MAX32       i;
410     NATIVE_UINT_MAX32       j;
411     UINT32                  GpeBlock;
412     UINT32                  GpeRegister;
413     UINT32                  GpeNumberIndex;
414     UINT32                  GpeNumber;
415     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
416     ACPI_STATUS             Status;
417
418
419     ACPI_FUNCTION_TRACE ("EvGpeInitialize");
420
421
422     /*
423      * Initialize the GPE Block globals
424      *
425      * Why the GPE register block lengths divided by 2:  From the ACPI Spec,
426      * section "General-Purpose Event Registers", we have:
427      *
428      * "Each register block contains two registers of equal length
429      *  GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
430      *  GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
431      *  The length of the GPE1_STS and GPE1_EN registers is equal to
432      *  half the GPE1_LEN. If a generic register block is not supported
433      *  then its respective block pointer and block length values in the
434      *  FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
435      *  to be the same size."
436      */
437     AcpiGbl_GpeBlockInfo[0].AddressSpaceId  = AcpiGbl_FADT->XGpe0Blk.AddressSpaceId;
438     AcpiGbl_GpeBlockInfo[1].AddressSpaceId  = AcpiGbl_FADT->XGpe1Blk.AddressSpaceId;
439
440     AcpiGbl_GpeBlockInfo[0].RegisterCount   = (UINT16) ACPI_DIV_16 (AcpiGbl_FADT->XGpe0Blk.RegisterBitWidth);
441     AcpiGbl_GpeBlockInfo[1].RegisterCount   = (UINT16) ACPI_DIV_16 (AcpiGbl_FADT->XGpe1Blk.RegisterBitWidth);
442
443     AcpiGbl_GpeBlockInfo[0].BlockAddress    = &AcpiGbl_FADT->XGpe0Blk;
444     AcpiGbl_GpeBlockInfo[1].BlockAddress    = &AcpiGbl_FADT->XGpe1Blk;
445
446     AcpiGbl_GpeBlockInfo[0].BlockBaseNumber = 0;
447     AcpiGbl_GpeBlockInfo[1].BlockBaseNumber = AcpiGbl_FADT->Gpe1Base;
448
449     /* Warn and exit if there are no GPE registers */
450
451     AcpiGbl_GpeRegisterCount = AcpiGbl_GpeBlockInfo[0].RegisterCount +
452                                AcpiGbl_GpeBlockInfo[1].RegisterCount;
453     if (!AcpiGbl_GpeRegisterCount)
454     {
455         ACPI_REPORT_WARNING (("There are no GPE blocks defined in the FADT\n"));
456         return_ACPI_STATUS (AE_OK);
457     }
458
459     /* 
460      * Determine the maximum GPE number for this machine.
461      * Note: both GPE0 and GPE1 are optional, and either can exist without
462      * the other
463      */
464     if (AcpiGbl_GpeBlockInfo[0].RegisterCount)
465     {
466         /* GPE block 0 exists */
467
468         AcpiGbl_GpeNumberMax = ACPI_MUL_8 (AcpiGbl_GpeBlockInfo[0].RegisterCount) - 1;
469     }
470
471     if (AcpiGbl_GpeBlockInfo[1].RegisterCount)
472     {
473         /* GPE block 1 exists */
474
475         /* Check for GPE0/GPE1 overlap (if both banks exist) */
476
477         if ((AcpiGbl_GpeBlockInfo[0].RegisterCount) &&
478             (AcpiGbl_GpeNumberMax >= AcpiGbl_FADT->Gpe1Base))
479         {
480             ACPI_REPORT_ERROR ((
481                 "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d)\n",
482                 AcpiGbl_GpeNumberMax, AcpiGbl_FADT->Gpe1Base, 
483                 AcpiGbl_FADT->Gpe1Base + (ACPI_MUL_8 (AcpiGbl_GpeBlockInfo[1].RegisterCount) - 1)));
484             return_ACPI_STATUS (AE_BAD_VALUE);
485         }
486
487         /* 
488          * GPE0 and GPE1 do not have to be contiguous in the GPE number space,
489          * But, GPE0 always starts at zero.
490          */
491         AcpiGbl_GpeNumberMax = AcpiGbl_FADT->Gpe1Base + 
492                                 (ACPI_MUL_8 (AcpiGbl_GpeBlockInfo[1].RegisterCount) - 1);
493     }
494
495     /* Check for Max GPE number out-of-range */
496
497     if (AcpiGbl_GpeNumberMax > ACPI_GPE_MAX)
498     {
499         ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n", 
500             AcpiGbl_GpeNumberMax));
501         return_ACPI_STATUS (AE_BAD_VALUE);
502     }
503
504     /* Allocate the GPE number-to-index translation table */
505
506     AcpiGbl_GpeNumberToIndex = ACPI_MEM_CALLOCATE (
507                                     sizeof (ACPI_GPE_INDEX_INFO) *
508                                     ((ACPI_SIZE) AcpiGbl_GpeNumberMax + 1));
509     if (!AcpiGbl_GpeNumberToIndex)
510     {
511         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
512             "Could not allocate the GpeNumberToIndex table\n"));
513         return_ACPI_STATUS (AE_NO_MEMORY);
514     }
515
516     /* Set the Gpe index table to GPE_INVALID */
517
518     ACPI_MEMSET (AcpiGbl_GpeNumberToIndex, (int) ACPI_GPE_INVALID,
519             sizeof (ACPI_GPE_INDEX_INFO) * ((ACPI_SIZE) AcpiGbl_GpeNumberMax + 1));
520
521     /* Allocate the GPE register information block */
522
523     AcpiGbl_GpeRegisterInfo = ACPI_MEM_CALLOCATE (
524                                 (ACPI_SIZE) AcpiGbl_GpeRegisterCount *
525                                 sizeof (ACPI_GPE_REGISTER_INFO));
526     if (!AcpiGbl_GpeRegisterInfo)
527     {
528         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
529             "Could not allocate the GpeRegisterInfo table\n"));
530         goto ErrorExit1;
531     }
532
533     /*
534      * Allocate the GPE dispatch handler block.  There are eight distinct GPEs
535      * per register.  Initialization to zeros is sufficient.
536      */
537     AcpiGbl_GpeNumberInfo = ACPI_MEM_CALLOCATE (
538                                 (ACPI_SIZE) ACPI_MUL_8 (AcpiGbl_GpeRegisterCount) *
539                                 sizeof (ACPI_GPE_NUMBER_INFO));
540     if (!AcpiGbl_GpeNumberInfo)
541     {
542         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the GpeNumberInfo table\n"));
543         goto ErrorExit2;
544     }
545
546     /*
547      * Initialize the GPE information and validation tables.  A goal of these
548      * tables is to hide the fact that there are two separate GPE register sets
549      * in a given gpe hardware block, the status registers occupy the first half,
550      * and the enable registers occupy the second half.  Another goal is to hide
551      * the fact that there may be multiple GPE hardware blocks.
552      */
553     GpeRegister = 0;
554     GpeNumberIndex = 0;
555
556     for (GpeBlock = 0; GpeBlock < ACPI_MAX_GPE_BLOCKS; GpeBlock++)
557     {
558         for (i = 0; i < AcpiGbl_GpeBlockInfo[GpeBlock].RegisterCount; i++)
559         {
560             GpeRegisterInfo = &AcpiGbl_GpeRegisterInfo[GpeRegister];
561
562             /* Init the Register info for this entire GPE register (8 GPEs) */
563
564             GpeRegisterInfo->BaseGpeNumber = (UINT8) (AcpiGbl_GpeBlockInfo[GpeBlock].BlockBaseNumber
565                                                         + (ACPI_MUL_8 (i)));
566
567             ACPI_STORE_ADDRESS (GpeRegisterInfo->StatusAddress.Address,
568                                 (ACPI_GET_ADDRESS (AcpiGbl_GpeBlockInfo[GpeBlock].BlockAddress->Address)
569                                     + i));
570
571             ACPI_STORE_ADDRESS (GpeRegisterInfo->EnableAddress.Address,
572                                 (ACPI_GET_ADDRESS (AcpiGbl_GpeBlockInfo[GpeBlock].BlockAddress->Address)
573                                     + i
574                                     + AcpiGbl_GpeBlockInfo[GpeBlock].RegisterCount));
575
576             GpeRegisterInfo->StatusAddress.AddressSpaceId    = AcpiGbl_GpeBlockInfo[GpeBlock].AddressSpaceId;
577             GpeRegisterInfo->EnableAddress.AddressSpaceId    = AcpiGbl_GpeBlockInfo[GpeBlock].AddressSpaceId;
578             GpeRegisterInfo->StatusAddress.RegisterBitWidth  = 8;
579             GpeRegisterInfo->EnableAddress.RegisterBitWidth  = 8;
580             GpeRegisterInfo->StatusAddress.RegisterBitOffset = 8;
581             GpeRegisterInfo->EnableAddress.RegisterBitOffset = 8;
582
583             /* Init the Index mapping info for each GPE number within this register */
584
585             for (j = 0; j < 8; j++)
586             {
587                 GpeNumber = GpeRegisterInfo->BaseGpeNumber + j;
588                 AcpiGbl_GpeNumberToIndex[GpeNumber].NumberIndex = (UINT8) GpeNumberIndex;
589
590                 AcpiGbl_GpeNumberInfo[GpeNumberIndex].BitMask = AcpiGbl_DecodeTo8bit[j];
591                 GpeNumberIndex++;
592             }
593
594             /*
595              * Clear the status/enable registers.  Note that status registers
596              * are cleared by writing a '1', while enable registers are cleared
597              * by writing a '0'.
598              */
599             Status = AcpiHwLowLevelWrite (8, 0x00, &GpeRegisterInfo->EnableAddress, 0);
600             if (ACPI_FAILURE (Status))
601             {
602                 return_ACPI_STATUS (Status);
603             }
604
605             Status = AcpiHwLowLevelWrite (8, 0xFF, &GpeRegisterInfo->StatusAddress, 0);
606             if (ACPI_FAILURE (Status))
607             {
608                 return_ACPI_STATUS (Status);
609             }
610
611             GpeRegister++;
612         }
613
614         if (i)
615         {
616             ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE Block%d: %X registers at %8.8X%8.8X\n",
617                 (INT32) GpeBlock, AcpiGbl_GpeBlockInfo[0].RegisterCount,
618                 ACPI_HIDWORD (ACPI_GET_ADDRESS (AcpiGbl_GpeBlockInfo[GpeBlock].BlockAddress->Address)),
619                 ACPI_LODWORD (ACPI_GET_ADDRESS (AcpiGbl_GpeBlockInfo[GpeBlock].BlockAddress->Address))));
620
621             ACPI_REPORT_INFO (("GPE Block%d defined as GPE%d to GPE%d\n",
622                 (INT32) GpeBlock,
623                 (UINT32) AcpiGbl_GpeBlockInfo[GpeBlock].BlockBaseNumber,
624                 (UINT32) (AcpiGbl_GpeBlockInfo[GpeBlock].BlockBaseNumber +
625                     ((AcpiGbl_GpeBlockInfo[GpeBlock].RegisterCount * 8) -1))));
626         }
627     }
628
629     return_ACPI_STATUS (AE_OK);
630
631
632     /* Error cleanup */
633
634 ErrorExit2:
635     ACPI_MEM_FREE (AcpiGbl_GpeRegisterInfo);
636
637 ErrorExit1:
638     ACPI_MEM_FREE (AcpiGbl_GpeNumberToIndex);
639     return_ACPI_STATUS (AE_NO_MEMORY);
640 }
641
642
643 /*******************************************************************************
644  *
645  * FUNCTION:    AcpiEvSaveMethodInfo
646  *
647  * PARAMETERS:  None
648  *
649  * RETURN:      None
650  *
651  * DESCRIPTION: Called from AcpiWalkNamespace.  Expects each object to be a
652  *              control method under the _GPE portion of the namespace.
653  *              Extract the name and GPE type from the object, saving this
654  *              information for quick lookup during GPE dispatch
655  *
656  *              The name of each GPE control method is of the form:
657  *                  "_Lnn" or "_Enn"
658  *              Where:
659  *                  L      - means that the GPE is level triggered
660  *                  E      - means that the GPE is edge triggered
661  *                  nn     - is the GPE number [in HEX]
662  *
663  ******************************************************************************/
664
665 static ACPI_STATUS
666 AcpiEvSaveMethodInfo (
667     ACPI_HANDLE             ObjHandle,
668     UINT32                  Level,
669     void                    *ObjDesc,
670     void                    **ReturnValue)
671 {
672     UINT32                  GpeNumber;
673     UINT32                  GpeNumberIndex;
674     NATIVE_CHAR             Name[ACPI_NAME_SIZE + 1];
675     UINT8                   Type;
676     ACPI_STATUS             Status;
677
678
679     ACPI_FUNCTION_NAME ("EvSaveMethodInfo");
680
681
682     /* Extract the name from the object and convert to a string */
683
684     ACPI_MOVE_UNALIGNED32_TO_32 (Name,
685                                 &((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Integer);
686     Name[ACPI_NAME_SIZE] = 0;
687
688     /*
689      * Edge/Level determination is based on the 2nd character of the method name
690      */
691     switch (Name[1])
692     {
693     case 'L':
694         Type = ACPI_EVENT_LEVEL_TRIGGERED;
695         break;
696
697     case 'E':
698         Type = ACPI_EVENT_EDGE_TRIGGERED;
699         break;
700
701     default:
702         /* Unknown method type, just ignore it! */
703
704         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
705             "Unknown GPE method type: %s (name not of form _Lnn or _Enn)\n",
706             Name));
707         return (AE_OK);
708     }
709
710     /* Convert the last two characters of the name to the GPE Number */
711
712     GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16);
713     if (GpeNumber == ACPI_UINT32_MAX)
714     {
715         /* Conversion failed; invalid method, just ignore it */
716
717         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
718             "Could not extract GPE number from name: %s (name not of form _Lnn or _Enn)\n",
719             Name));
720         return (AE_OK);
721     }
722
723     /* Get GPE index and ensure that we have a valid GPE number */
724
725     GpeNumberIndex = AcpiEvGetGpeNumberIndex (GpeNumber);
726     if (GpeNumberIndex == ACPI_GPE_INVALID)
727     {
728         /* Not valid, all we can do here is ignore it */
729
730         return (AE_OK);
731     }
732
733     /*
734      * Now we can add this information to the GpeInfo block
735      * for use during dispatch of this GPE.
736      */
737     AcpiGbl_GpeNumberInfo [GpeNumberIndex].Type         = Type;
738     AcpiGbl_GpeNumberInfo [GpeNumberIndex].MethodHandle = ObjHandle;
739
740     /*
741      * Enable the GPE (SCIs should be disabled at this point)
742      */
743     Status = AcpiHwEnableGpe (GpeNumber);
744     if (ACPI_FAILURE (Status))
745     {
746         return (Status);
747     }
748
749     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %X\n",
750         Name, GpeNumber));
751     return (AE_OK);
752 }
753
754
755 /*******************************************************************************
756  *
757  * FUNCTION:    AcpiEvInitGpeControlMethods
758  *
759  * PARAMETERS:  None
760  *
761  * RETURN:      Status
762  *
763  * DESCRIPTION: Obtain the control methods associated with the GPEs.
764  *              NOTE: Must be called AFTER namespace initialization!
765  *
766  ******************************************************************************/
767
768 ACPI_STATUS
769 AcpiEvInitGpeControlMethods (void)
770 {
771     ACPI_STATUS             Status;
772
773
774     ACPI_FUNCTION_TRACE ("EvInitGpeControlMethods");
775
776
777     /* Get a permanent handle to the _GPE object */
778
779     Status = AcpiGetHandle (NULL, "\\_GPE", &AcpiGbl_GpeObjHandle);
780     if (ACPI_FAILURE (Status))
781     {
782         return_ACPI_STATUS (Status);
783     }
784
785     /* Traverse the namespace under \_GPE to find all methods there */
786
787     Status = AcpiWalkNamespace (ACPI_TYPE_METHOD, AcpiGbl_GpeObjHandle,
788                                 ACPI_UINT32_MAX, AcpiEvSaveMethodInfo,
789                                 NULL, NULL);
790
791     return_ACPI_STATUS (Status);
792 }
793
794
795 /*******************************************************************************
796  *
797  * FUNCTION:    AcpiEvGpeDetect
798  *
799  * PARAMETERS:  None
800  *
801  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
802  *
803  * DESCRIPTION: Detect if any GP events have occurred.  This function is
804  *              executed at interrupt level.
805  *
806  ******************************************************************************/
807
808 UINT32
809 AcpiEvGpeDetect (void)
810 {
811     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
812     UINT32                  i;
813     UINT32                  j;
814     UINT8                   EnabledStatusByte;
815     UINT8                   BitMask;
816     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
817     UINT32                  InValue;
818     ACPI_STATUS             Status;
819
820
821     ACPI_FUNCTION_NAME ("EvGpeDetect");
822
823
824     /*
825      * Read all of the 8-bit GPE status and enable registers
826      * in both of the register blocks, saving all of it.
827      * Find all currently active GP events.
828      */
829     for (i = 0; i < AcpiGbl_GpeRegisterCount; i++)
830     {
831         GpeRegisterInfo = &AcpiGbl_GpeRegisterInfo[i];
832
833         Status = AcpiHwLowLevelRead (8, &InValue, &GpeRegisterInfo->StatusAddress, 0);
834         GpeRegisterInfo->Status = (UINT8) InValue;
835         if (ACPI_FAILURE (Status))
836         {
837             return (ACPI_INTERRUPT_NOT_HANDLED);
838         }
839
840         Status = AcpiHwLowLevelRead (8, &InValue, &GpeRegisterInfo->EnableAddress, 0);
841         GpeRegisterInfo->Enable = (UINT8) InValue;
842         if (ACPI_FAILURE (Status))
843         {
844             return (ACPI_INTERRUPT_NOT_HANDLED);
845         }
846
847         ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
848             "GPE block at %8.8X%8.8X - Values: Enable %02X Status %02X\n",
849             ACPI_HIDWORD (ACPI_GET_ADDRESS (GpeRegisterInfo->EnableAddress.Address)),
850             ACPI_LODWORD (ACPI_GET_ADDRESS (GpeRegisterInfo->EnableAddress.Address)),
851             GpeRegisterInfo->Enable,
852             GpeRegisterInfo->Status));
853
854         /* First check if there is anything active at all in this register */
855
856         EnabledStatusByte = (UINT8) (GpeRegisterInfo->Status &
857                                      GpeRegisterInfo->Enable);
858         if (!EnabledStatusByte)
859         {
860             /* No active GPEs in this register, move on */
861
862             continue;
863         }
864
865         /* Now look at the individual GPEs in this byte register */
866
867         for (j = 0, BitMask = 1; j < 8; j++, BitMask <<= 1)
868         {
869             /* Examine one GPE bit */
870
871             if (EnabledStatusByte & BitMask)
872             {
873                 /*
874                  * Found an active GPE.  Dispatch the event to a handler
875                  * or method.
876                  */
877                 IntStatus |= AcpiEvGpeDispatch (
878                                 GpeRegisterInfo->BaseGpeNumber + j);
879             }
880         }
881     }
882
883     return (IntStatus);
884 }
885
886
887 /*******************************************************************************
888  *
889  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
890  *
891  * PARAMETERS:  GpeNumber       - The 0-based GPE number
892  *
893  * RETURN:      None
894  *
895  * DESCRIPTION: Perform the actual execution of a GPE control method.  This
896  *              function is called from an invocation of AcpiOsQueueForExecution
897  *              (and therefore does NOT execute at interrupt level) so that
898  *              the control method itself is not executed in the context of
899  *              the SCI interrupt handler.
900  *
901  ******************************************************************************/
902
903 static void ACPI_SYSTEM_XFACE
904 AcpiEvAsynchExecuteGpeMethod (
905     void                    *Context)
906 {
907     UINT32                  GpeNumber = (UINT32) ACPI_TO_INTEGER (Context);
908     UINT32                  GpeNumberIndex;
909     ACPI_GPE_NUMBER_INFO    GpeInfo;
910     ACPI_STATUS             Status;
911
912
913     ACPI_FUNCTION_TRACE ("EvAsynchExecuteGpeMethod");
914
915
916     GpeNumberIndex = AcpiEvGetGpeNumberIndex (GpeNumber);
917     if (GpeNumberIndex == ACPI_GPE_INVALID)
918     {
919         return_VOID;
920     }
921
922     /*
923      * Take a snapshot of the GPE info for this level - we copy the
924      * info to prevent a race condition with RemoveHandler.
925      */
926     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
927     if (ACPI_FAILURE (Status))
928     {
929         return_VOID;
930     }
931
932     GpeInfo = AcpiGbl_GpeNumberInfo [GpeNumberIndex];
933     Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
934     if (ACPI_FAILURE (Status))
935     {
936         return_VOID;
937     }
938
939     if (GpeInfo.MethodHandle)
940     {
941         /*
942          * Invoke the GPE Method (_Lxx, _Exx):
943          * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.)
944          */
945         Status = AcpiNsEvaluateByHandle (GpeInfo.MethodHandle, NULL, NULL);
946         if (ACPI_FAILURE (Status))
947         {
948             ACPI_REPORT_ERROR (("%s while evaluating GPE%X method\n",
949                 AcpiFormatException (Status), GpeNumber));
950         }
951     }
952
953     if (GpeInfo.Type & ACPI_EVENT_LEVEL_TRIGGERED)
954     {
955         /*
956          * GPE is level-triggered, we clear the GPE status bit after handling
957          * the event.
958          */
959         Status = AcpiHwClearGpe (GpeNumber);
960         if (ACPI_FAILURE (Status))
961         {
962             return_VOID;
963         }
964     }
965
966     /*
967      * Enable the GPE.
968      */
969     (void) AcpiHwEnableGpe (GpeNumber);
970     return_VOID;
971 }
972
973
974 /*******************************************************************************
975  *
976  * FUNCTION:    AcpiEvGpeDispatch
977  *
978  * PARAMETERS:  GpeNumber       - The 0-based GPE number
979  *
980  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
981  *
982  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
983  *              or method (e.g. _Lxx/_Exx) handler.  This function executes
984  *              at interrupt level.
985  *
986  ******************************************************************************/
987
988 UINT32
989 AcpiEvGpeDispatch (
990     UINT32                  GpeNumber)
991 {
992     UINT32                  GpeNumberIndex;
993     ACPI_GPE_NUMBER_INFO    *GpeInfo;
994     ACPI_STATUS             Status;
995
996
997     ACPI_FUNCTION_TRACE ("EvGpeDispatch");
998
999
1000     GpeNumberIndex = AcpiEvGetGpeNumberIndex (GpeNumber);
1001     if (GpeNumberIndex == ACPI_GPE_INVALID)
1002     {
1003         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "GPE[%X] is not a valid event\n", GpeNumber));
1004         return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
1005     }
1006
1007     /*
1008      * We don't have to worry about mutex on GpeInfo because we are
1009      * executing at interrupt level.
1010      */
1011     GpeInfo = &AcpiGbl_GpeNumberInfo [GpeNumberIndex];
1012
1013     /*
1014      * If edge-triggered, clear the GPE status bit now.  Note that
1015      * level-triggered events are cleared after the GPE is serviced.
1016      */
1017     if (GpeInfo->Type & ACPI_EVENT_EDGE_TRIGGERED)
1018     {
1019         Status = AcpiHwClearGpe (GpeNumber);
1020         if (ACPI_FAILURE (Status))
1021         {
1022             ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to clear GPE[%X]\n", GpeNumber));
1023             return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
1024         }
1025     }
1026
1027     /*
1028      * Dispatch the GPE to either an installed handler, or the control
1029      * method associated with this GPE (_Lxx or _Exx).
1030      * If a handler exists, we invoke it and do not attempt to run the method.
1031      * If there is neither a handler nor a method, we disable the level to
1032      * prevent further events from coming in here.
1033      */
1034     if (GpeInfo->Handler)
1035     {
1036         /* Invoke the installed handler (at interrupt level) */
1037
1038         GpeInfo->Handler (GpeInfo->Context);
1039     }
1040     else if (GpeInfo->MethodHandle)
1041     {
1042         /*
1043          * Disable GPE, so it doesn't keep firing before the method has a
1044          * chance to run.
1045          */
1046         Status = AcpiHwDisableGpe (GpeNumber);
1047         if (ACPI_FAILURE (Status))
1048         {
1049             ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to disable GPE[%X]\n", GpeNumber));
1050             return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
1051         }
1052
1053         /*
1054          * Execute the method associated with the GPE.
1055          */
1056         if (ACPI_FAILURE (AcpiOsQueueForExecution (OSD_PRIORITY_GPE,
1057                                 AcpiEvAsynchExecuteGpeMethod,
1058                                 ACPI_TO_POINTER (GpeNumber))))
1059         {
1060             ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to queue handler for GPE[%X], event is disabled\n", GpeNumber));
1061         }
1062     }
1063     else
1064     {
1065         /* No handler or method to run! */
1066
1067         ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: No handler or method for GPE[%X], disabling event\n", GpeNumber));
1068
1069         /*
1070          * Disable the GPE.  The GPE will remain disabled until the ACPI
1071          * Core Subsystem is restarted, or the handler is reinstalled.
1072          */
1073         Status = AcpiHwDisableGpe (GpeNumber);
1074         if (ACPI_FAILURE (Status))
1075         {
1076             ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to disable GPE[%X]\n", GpeNumber));
1077             return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
1078         }
1079     }
1080
1081     /*
1082      * It is now safe to clear level-triggered evnets.
1083      */
1084     if (GpeInfo->Type & ACPI_EVENT_LEVEL_TRIGGERED)
1085     {
1086         Status = AcpiHwClearGpe (GpeNumber);
1087         if (ACPI_FAILURE (Status))
1088         {
1089             ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to clear GPE[%X]\n", GpeNumber));
1090             return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
1091         }
1092     }
1093
1094     return_VALUE (ACPI_INTERRUPT_HANDLED);
1095 }