Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1498 serge 1
/******************************************************************************
2
 *
3
 * Module Name: aehandlers - Various handlers for acpiexec
4
 *
5
 *****************************************************************************/
6
 
7
/******************************************************************************
8
 *
9
 * 1. Copyright Notice
10
 *
11
 * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
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
#include "aecommon.h"
117
 
118
#define _COMPONENT          ACPI_TOOLS
119
        ACPI_MODULE_NAME    ("aehandlers")
120
 
121
/* Local prototypes */
122
 
123
void
124
AeNotifyHandler (
125
    ACPI_HANDLE             Device,
126
    UINT32                  Value,
127
    void                    *Context);
128
 
129
void
130
AeDeviceNotifyHandler (
131
    ACPI_HANDLE             Device,
132
    UINT32                  Value,
133
    void                    *Context);
134
 
135
ACPI_STATUS
136
AeExceptionHandler (
137
    ACPI_STATUS             AmlStatus,
138
    ACPI_NAME               Name,
139
    UINT16                  Opcode,
140
    UINT32                  AmlOffset,
141
    void                    *Context);
142
 
143
ACPI_STATUS
144
AeTableHandler (
145
    UINT32                  Event,
146
    void                    *Table,
147
    void                    *Context);
148
 
149
ACPI_STATUS
150
AeRegionInit (
151
    ACPI_HANDLE             RegionHandle,
152
    UINT32                  Function,
153
    void                    *HandlerContext,
154
    void                    **RegionContext);
155
 
156
void
157
AeAttachedDataHandler (
158
    ACPI_HANDLE             Object,
159
    void                    *Data);
160
 
161
UINT32                      SigintCount = 0;
162
AE_DEBUG_REGIONS            AeRegions;
163
 
164
 
165
/******************************************************************************
166
 *
167
 * FUNCTION:    AeCtrlCHandler
168
 *
169
 * PARAMETERS:  Sig
170
 *
171
 * RETURN:      none
172
 *
173
 * DESCRIPTION: Control-C handler.  Abort running control method if any.
174
 *
175
 *****************************************************************************/
176
 
177
void __cdecl
178
AeCtrlCHandler (
179
    int                     Sig)
180
{
181
 
182
    signal (SIGINT, SIG_IGN);
183
    SigintCount++;
184
 
185
    AcpiOsPrintf ("Caught a ctrl-c (#%u)\n\n", SigintCount);
186
 
187
    if (AcpiGbl_MethodExecuting)
188
    {
189
        AcpiGbl_AbortMethod = TRUE;
190
        signal (SIGINT, AeCtrlCHandler);
191
 
192
        if (SigintCount < 10)
193
        {
194
            return;
195
        }
196
    }
197
 
198
    exit (0);
199
}
200
 
201
 
202
/******************************************************************************
203
 *
204
 * FUNCTION:    AeNotifyHandler
205
 *
206
 * PARAMETERS:  Standard notify handler parameters
207
 *
208
 * RETURN:      Status
209
 *
210
 * DESCRIPTION: System notify handler for AcpiExec utility.  Used by the ASL
211
 *              test suite(s) to communicate errors and other information to
212
 *              this utility via the Notify() operator.
213
 *
214
 *****************************************************************************/
215
 
216
void
217
AeNotifyHandler (
218
    ACPI_HANDLE                 Device,
219
    UINT32                      Value,
220
    void                        *Context)
221
{
222
 
223
    switch (Value)
224
    {
225
#if 0
226
    case 0:
227
        printf ("[AcpiExec] Method Error 0x%X: Results not equal\n", Value);
228
        if (AcpiGbl_DebugFile)
229
        {
230
            AcpiOsPrintf ("[AcpiExec] Method Error: Results not equal\n");
231
        }
232
        break;
233
 
234
 
235
    case 1:
236
        printf ("[AcpiExec] Method Error: Incorrect numeric result\n");
237
        if (AcpiGbl_DebugFile)
238
        {
239
            AcpiOsPrintf ("[AcpiExec] Method Error: Incorrect numeric result\n");
240
        }
241
        break;
242
 
243
 
244
    case 2:
245
        printf ("[AcpiExec] Method Error: An operand was overwritten\n");
246
        if (AcpiGbl_DebugFile)
247
        {
248
            AcpiOsPrintf ("[AcpiExec] Method Error: An operand was overwritten\n");
249
        }
250
        break;
251
 
252
#endif
253
 
254
    default:
255
        printf ("[AcpiExec] Received a System Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
256
            AcpiUtGetNodeName (Device), Device, Value,
257
            AcpiUtGetNotifyName (Value));
258
        if (AcpiGbl_DebugFile)
259
        {
260
            AcpiOsPrintf ("[AcpiExec] Received a system notify, Value 0x%2.2X\n", Value);
261
        }
262
 
263
        (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
264
        break;
265
    }
266
 
267
}
268
 
269
 
270
/******************************************************************************
271
 *
272
 * FUNCTION:    AeDeviceNotifyHandler
273
 *
274
 * PARAMETERS:  Standard notify handler parameters
275
 *
276
 * RETURN:      Status
277
 *
278
 * DESCRIPTION: Device notify handler for AcpiExec utility.  Used by the ASL
279
 *              test suite(s) to communicate errors and other information to
280
 *              this utility via the Notify() operator.
281
 *
282
 *****************************************************************************/
283
 
284
void
285
AeDeviceNotifyHandler (
286
    ACPI_HANDLE                 Device,
287
    UINT32                      Value,
288
    void                        *Context)
289
{
290
 
291
    printf ("[AcpiExec] Received a Device Notify on [%4.4s] %p Value 0x%2.2X (%s)\n",
292
        AcpiUtGetNodeName (Device), Device, Value,
293
        AcpiUtGetNotifyName (Value));
294
    if (AcpiGbl_DebugFile)
295
    {
296
        AcpiOsPrintf ("[AcpiExec] Received a device notify, Value 0x%2.2X\n", Value);
297
    }
298
 
299
    (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL);
300
}
301
 
302
 
303
/******************************************************************************
304
 *
305
 * FUNCTION:    AeExceptionHandler
306
 *
307
 * PARAMETERS:  Standard exception handler parameters
308
 *
309
 * RETURN:      Status
310
 *
311
 * DESCRIPTION: System exception handler for AcpiExec utility.
312
 *
313
 *****************************************************************************/
314
 
315
ACPI_STATUS
316
AeExceptionHandler (
317
    ACPI_STATUS             AmlStatus,
318
    ACPI_NAME               Name,
319
    UINT16                  Opcode,
320
    UINT32                  AmlOffset,
321
    void                    *Context)
322
{
323
    ACPI_STATUS             NewAmlStatus = AmlStatus;
324
    ACPI_STATUS             Status;
325
    ACPI_BUFFER             ReturnObj;
326
    ACPI_OBJECT_LIST        ArgList;
327
    ACPI_OBJECT             Arg[3];
328
    const char              *Exception;
329
 
330
 
331
    Exception = AcpiFormatException (AmlStatus);
332
    AcpiOsPrintf ("[AcpiExec] Exception %s during execution ", Exception);
333
    if (Name)
334
    {
335
        AcpiOsPrintf ("of method [%4.4s]", (char *) &Name);
336
    }
337
    else
338
    {
339
        AcpiOsPrintf ("at module level (table load)");
340
    }
341
    AcpiOsPrintf (" Opcode [%s] @%X\n", AcpiPsGetOpcodeName (Opcode), AmlOffset);
342
 
343
    /*
344
     * Invoke the _ERR method if present
345
     *
346
     * Setup parameter object
347
     */
348
    ArgList.Count = 3;
349
    ArgList.Pointer = Arg;
350
 
351
    Arg[0].Type = ACPI_TYPE_INTEGER;
352
    Arg[0].Integer.Value = AmlStatus;
353
 
354
    Arg[1].Type = ACPI_TYPE_STRING;
355
    Arg[1].String.Pointer = ACPI_CAST_PTR (char, Exception);
356
    Arg[1].String.Length = ACPI_STRLEN (Exception);
357
 
358
    Arg[2].Type = ACPI_TYPE_INTEGER;
359
    Arg[2].Integer.Value = ACPI_TO_INTEGER (AcpiOsGetThreadId());
360
 
361
    /* Setup return buffer */
362
 
363
    ReturnObj.Pointer = NULL;
364
    ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
365
 
366
    Status = AcpiEvaluateObject (NULL, "\\_ERR", &ArgList, &ReturnObj);
367
    if (ACPI_SUCCESS (Status))
368
    {
369
        if (ReturnObj.Pointer)
370
        {
371
            /* Override original status */
372
 
373
            NewAmlStatus = (ACPI_STATUS)
374
                ((ACPI_OBJECT *) ReturnObj.Pointer)->Integer.Value;
375
 
376
            AcpiOsFree (ReturnObj.Pointer);
377
        }
378
    }
379
    else if (Status != AE_NOT_FOUND)
380
    {
381
        AcpiOsPrintf ("[AcpiExec] Could not execute _ERR method, %s\n",
382
            AcpiFormatException (Status));
383
    }
384
 
385
    /* Global override */
386
 
387
    if (AcpiGbl_IgnoreErrors)
388
    {
389
        NewAmlStatus = AE_OK;
390
    }
391
 
392
    if (NewAmlStatus != AmlStatus)
393
    {
394
        AcpiOsPrintf ("[AcpiExec] Exception override, new status %s\n",
395
            AcpiFormatException (NewAmlStatus));
396
    }
397
 
398
    return (NewAmlStatus);
399
}
400
 
401
 
402
/******************************************************************************
403
 *
404
 * FUNCTION:    AeTableHandler
405
 *
406
 * PARAMETERS:  Table handler
407
 *
408
 * RETURN:      Status
409
 *
410
 * DESCRIPTION: System table handler for AcpiExec utility.
411
 *
412
 *****************************************************************************/
413
 
414
char                *TableEvents[] =
415
{
416
    "LOAD",
417
    "UNLOAD",
418
    "UNKNOWN"
419
};
420
 
421
ACPI_STATUS
422
AeTableHandler (
423
    UINT32                  Event,
424
    void                    *Table,
425
    void                    *Context)
426
{
427
 
428
    if (Event > ACPI_NUM_TABLE_EVENTS)
429
    {
430
        Event = ACPI_NUM_TABLE_EVENTS;
431
    }
432
 
433
    /* TBD: could dump entire table header, need a header dump routine */
434
 
435
    printf ("[AcpiExec] Table Event %s, [%4.4s] %p\n",
436
        TableEvents[Event], ((ACPI_TABLE_HEADER *) Table)->Signature, Table);
437
    return (AE_OK);
438
}
439
 
440
 
441
/******************************************************************************
442
 *
443
 * FUNCTION:    AeGpeHandler
444
 *
445
 * DESCRIPTION: GPE handler for acpiexec
446
 *
447
 *****************************************************************************/
448
 
449
UINT32
450
AeGpeHandler (
451
    void                    *Context)
452
{
453
    AcpiOsPrintf ("Received a GPE at handler\n");
454
    return (0);
455
}
456
 
457
 
458
/******************************************************************************
459
 *
460
 * FUNCTION:    AeAttachedDataHandler
461
 *
462
 * DESCRIPTION: Handler for deletion of nodes with attached data (attached via
463
 *              AcpiAttachData)
464
 *
465
 *****************************************************************************/
466
 
467
void
468
AeAttachedDataHandler (
469
    ACPI_HANDLE             Object,
470
    void                    *Data)
471
{
472
    ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Data);
473
 
474
 
475
    AcpiOsPrintf ("Received an attached data deletion on %4.4s\n",
476
        Node->Name.Ascii);
477
}
478
 
479
 
480
/******************************************************************************
481
 *
482
 * FUNCTION:    AeRegionInit
483
 *
484
 * PARAMETERS:  None
485
 *
486
 * RETURN:      Status
487
 *
488
 * DESCRIPTION: Opregion init function.
489
 *
490
 *****************************************************************************/
491
 
492
ACPI_STATUS
493
AeRegionInit (
494
    ACPI_HANDLE                 RegionHandle,
495
    UINT32                      Function,
496
    void                        *HandlerContext,
497
    void                        **RegionContext)
498
{
499
    /*
500
     * Real simple, set the RegionContext to the RegionHandle
501
     */
502
    *RegionContext = RegionHandle;
503
 
504
    return AE_OK;
505
}
506
 
507
 
508
/******************************************************************************
509
 *
510
 * FUNCTION:    AeInstallHandlers
511
 *
512
 * PARAMETERS:  None
513
 *
514
 * RETURN:      Status
515
 *
516
 * DESCRIPTION: Install handlers for the AcpiExec utility.
517
 *
518
 *****************************************************************************/
519
 
520
ACPI_ADR_SPACE_TYPE         SpaceId[] = {0, 1, 2, 3, 4, 5, 6, 7, 0x80};
521
#define AEXEC_NUM_REGIONS   9
522
 
523
ACPI_STATUS
524
AeInstallHandlers (void)
525
{
526
    ACPI_STATUS             Status;
527
    UINT32                  i;
528
    ACPI_HANDLE             Handle;
529
 
530
 
531
    ACPI_FUNCTION_ENTRY ();
532
 
533
 
534
    Status = AcpiInstallTableHandler (AeTableHandler, NULL);
535
    if (ACPI_FAILURE (Status))
536
    {
537
        printf ("Could not install table handler, %s\n",
538
            AcpiFormatException (Status));
539
    }
540
 
541
    Status = AcpiInstallExceptionHandler (AeExceptionHandler);
542
    if (ACPI_FAILURE (Status))
543
    {
544
        printf ("Could not install exception handler, %s\n",
545
            AcpiFormatException (Status));
546
    }
547
 
548
    /* Install global notify handler */
549
 
550
    Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
551
                                        AeNotifyHandler, NULL);
552
    if (ACPI_FAILURE (Status))
553
    {
554
        printf ("Could not install a global notify handler, %s\n",
555
            AcpiFormatException (Status));
556
    }
557
 
558
    Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY,
559
                                        AeDeviceNotifyHandler, NULL);
560
    if (ACPI_FAILURE (Status))
561
    {
562
        printf ("Could not install a global notify handler, %s\n",
563
            AcpiFormatException (Status));
564
    }
565
 
566
    Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
567
    if (ACPI_SUCCESS (Status))
568
    {
569
        Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
570
                                            AeNotifyHandler, NULL);
571
        if (ACPI_FAILURE (Status))
572
        {
573
            printf ("Could not install a notify handler, %s\n",
574
                AcpiFormatException (Status));
575
        }
576
 
577
        Status = AcpiRemoveNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY,
578
                                            AeNotifyHandler);
579
        if (ACPI_FAILURE (Status))
580
        {
581
            printf ("Could not remove a notify handler, %s\n",
582
                AcpiFormatException (Status));
583
        }
584
 
585
        Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
586
                                            AeNotifyHandler, NULL);
587
        Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY,
588
                                            AeNotifyHandler);
589
        Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY,
590
                                            AeNotifyHandler, NULL);
591
        if (ACPI_FAILURE (Status))
592
        {
593
            printf ("Could not install a notify handler, %s\n",
594
                AcpiFormatException (Status));
595
        }
596
 
597
        Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
598
        Status = AcpiDetachData (Handle, AeAttachedDataHandler);
599
        Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle);
600
    }
601
    else
602
    {
603
        printf ("No _SB_ found, %s\n", AcpiFormatException (Status));
604
    }
605
 
606
    /* Set a handler for all supported operation regions */
607
 
608
    for (i = 0; i < AEXEC_NUM_REGIONS; i++)
609
    {
610
        Status = AcpiRemoveAddressSpaceHandler (AcpiGbl_RootNode,
611
                        SpaceId[i], AeRegionHandler);
612
 
613
        /* Install handler at the root object.
614
         * TBD: all default handlers should be installed here!
615
         */
616
        Status = AcpiInstallAddressSpaceHandler (AcpiGbl_RootNode,
617
                        SpaceId[i], AeRegionHandler, AeRegionInit, NULL);
618
        if (ACPI_FAILURE (Status))
619
        {
620
            ACPI_EXCEPTION ((AE_INFO, Status,
621
                "Could not install an OpRegion handler for %s space(%u)",
622
                AcpiUtGetRegionName((UINT8) SpaceId[i]), SpaceId[i]));
623
            return (Status);
624
        }
625
    }
626
 
627
    /*
628
     * Initialize the global Region Handler space
629
     * MCW 3/23/00
630
     */
631
    AeRegions.NumberOfRegions = 0;
632
    AeRegions.RegionList = NULL;
633
 
634
    return Status;
635
}
636
 
637
 
638
/******************************************************************************
639
 *
640
 * FUNCTION:    AeRegionHandler
641
 *
642
 * PARAMETERS:  Standard region handler parameters
643
 *
644
 * RETURN:      Status
645
 *
646
 * DESCRIPTION: Test handler - Handles some dummy regions via memory that can
647
 *              be manipulated in Ring 3. Simulates actual reads and writes.
648
 *
649
 *****************************************************************************/
650
 
651
ACPI_STATUS
652
AeRegionHandler (
653
    UINT32                  Function,
654
    ACPI_PHYSICAL_ADDRESS   Address,
655
    UINT32                  BitWidth,
656
    UINT64                  *Value,
657
    void                    *HandlerContext,
658
    void                    *RegionContext)
659
{
660
 
661
    ACPI_OPERAND_OBJECT     *RegionObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, RegionContext);
662
    UINT8                   *Buffer = ACPI_CAST_PTR (UINT8, Value);
663
    ACPI_PHYSICAL_ADDRESS   BaseAddress;
664
    ACPI_SIZE               Length;
665
    BOOLEAN                 BufferExists;
666
    AE_REGION               *RegionElement;
667
    void                    *BufferValue;
668
    ACPI_STATUS             Status;
669
    UINT32                  ByteWidth;
670
    UINT32                  i;
671
    UINT8                   SpaceId;
672
 
673
 
674
    ACPI_FUNCTION_NAME (AeRegionHandler);
675
 
676
    /*
677
     * If the object is not a region, simply return
678
     */
679
    if (RegionObject->Region.Type != ACPI_TYPE_REGION)
680
    {
681
        return AE_OK;
682
    }
683
 
684
    /*
685
     * Region support can be disabled with the -r option.
686
     * We use this to support dynamically loaded tables where we pass a valid
687
     * address to the AML.
688
     */
689
    if (AcpiGbl_DbOpt_NoRegionSupport)
690
    {
691
        BufferValue = ACPI_TO_POINTER (Address);
692
        ByteWidth = (BitWidth / 8);
693
 
694
        if (BitWidth % 8)
695
        {
696
            ByteWidth += 1;
697
        }
698
        goto DoFunction;
699
    }
700
 
701
    /*
702
     * Find the region's address space and length before searching
703
     * the linked list.
704
     */
705
    BaseAddress = RegionObject->Region.Address;
706
    Length = (ACPI_SIZE) RegionObject->Region.Length;
707
    SpaceId = RegionObject->Region.SpaceId;
708
 
709
    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Operation Region request on %s at 0x%X\n",
710
            AcpiUtGetRegionName (RegionObject->Region.SpaceId),
711
            (UINT32) Address));
712
 
713
    switch (SpaceId)
714
    {
715
    case ACPI_ADR_SPACE_SYSTEM_IO:
716
        /*
717
         * For I/O space, exercise the port validation
718
         */
719
        switch (Function & ACPI_IO_MASK)
720
        {
721
        case ACPI_READ:
722
            Status = AcpiHwReadPort (Address, (UINT32 *) Value, BitWidth);
723
            break;
724
 
725
        case ACPI_WRITE:
726
            Status = AcpiHwWritePort (Address, (UINT32) *Value, BitWidth);
727
            break;
728
 
729
        default:
730
            Status = AE_BAD_PARAMETER;
731
            break;
732
        }
733
 
734
        if (ACPI_FAILURE (Status))
735
        {
736
            return (Status);
737
        }
738
 
739
        /* Now go ahead and simulate the hardware */
740
        break;
741
 
742
 
743
    case ACPI_ADR_SPACE_SMBUS:
744
 
745
        Length = 0;
746
 
747
        switch (Function & ACPI_IO_MASK)
748
        {
749
        case ACPI_READ:
750
            switch (Function >> 16)
751
            {
752
            case AML_FIELD_ATTRIB_SMB_QUICK:
753
            case AML_FIELD_ATTRIB_SMB_SEND_RCV:
754
            case AML_FIELD_ATTRIB_SMB_BYTE:
755
                Length = 1;
756
                break;
757
 
758
            case AML_FIELD_ATTRIB_SMB_WORD:
759
            case AML_FIELD_ATTRIB_SMB_WORD_CALL:
760
                Length = 2;
761
                break;
762
 
763
            case AML_FIELD_ATTRIB_SMB_BLOCK:
764
            case AML_FIELD_ATTRIB_SMB_BLOCK_CALL:
765
                Length = 32;
766
                break;
767
 
768
            default:
769
                break;
770
            }
771
            break;
772
 
773
        case ACPI_WRITE:
774
            switch (Function >> 16)
775
            {
776
            case AML_FIELD_ATTRIB_SMB_QUICK:
777
            case AML_FIELD_ATTRIB_SMB_SEND_RCV:
778
            case AML_FIELD_ATTRIB_SMB_BYTE:
779
            case AML_FIELD_ATTRIB_SMB_WORD:
780
            case AML_FIELD_ATTRIB_SMB_BLOCK:
781
                Length = 0;
782
                break;
783
 
784
            case AML_FIELD_ATTRIB_SMB_WORD_CALL:
785
                Length = 2;
786
                break;
787
 
788
            case AML_FIELD_ATTRIB_SMB_BLOCK_CALL:
789
                Length = 32;
790
                break;
791
 
792
            default:
793
                break;
794
            }
795
            break;
796
 
797
        default:
798
            break;
799
        }
800
 
801
        for (i = 0; i < Length; i++)
802
        {
803
            Buffer[i+2] = (UINT8) (0xA0 + i);
804
        }
805
 
806
        Buffer[0] = 0x7A;
807
        Buffer[1] = (UINT8) Length;
808
        return (AE_OK);
809
 
810
 
811
    case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */
812
 
813
        AcpiOsPrintf ("AcpiExec: Received IPMI request: "
814
            "Address %X BaseAddress %X Length %X Width %X BufferLength %u\n",
815
            (UINT32) Address, (UINT32) BaseAddress,
816
            Length, BitWidth, Buffer[1]);
817
 
818
        /*
819
         * Regardless of a READ or WRITE, this handler is passed a 66-byte
820
         * buffer in which to return the IPMI status/length/data.
821
         *
822
         * Return some example data to show use of the bidirectional buffer
823
         */
824
        Buffer[0] = 0;       /* Status byte */
825
        Buffer[1] = 64;      /* Return buffer data length */
826
        Buffer[2] = 0;       /* Completion code */
827
        Buffer[3] = 0x34;    /* Power measurement */
828
        Buffer[4] = 0x12;    /* Power measurement */
829
        Buffer[65] = 0xEE;   /* last buffer byte */
830
        return (AE_OK);
831
 
832
    default:
833
        break;
834
    }
835
 
836
    /*
837
     * Search through the linked list for this region's buffer
838
     */
839
    BufferExists = FALSE;
840
    RegionElement = AeRegions.RegionList;
841
 
842
    if (AeRegions.NumberOfRegions)
843
    {
844
        while (!BufferExists && RegionElement)
845
        {
846
            if (RegionElement->Address == BaseAddress &&
847
                RegionElement->Length == Length &&
848
                RegionElement->SpaceId == SpaceId)
849
            {
850
                BufferExists = TRUE;
851
            }
852
            else
853
            {
854
                RegionElement = RegionElement->NextRegion;
855
            }
856
        }
857
    }
858
 
859
    /*
860
     * If the Region buffer does not exist, create it now
861
     */
862
    if (!BufferExists)
863
    {
864
        /*
865
         * Do the memory allocations first
866
         */
867
        RegionElement = AcpiOsAllocate (sizeof (AE_REGION));
868
        if (!RegionElement)
869
        {
870
            return AE_NO_MEMORY;
871
        }
872
 
873
        RegionElement->Buffer = AcpiOsAllocate (Length);
874
        if (!RegionElement->Buffer)
875
        {
876
            AcpiOsFree (RegionElement);
877
            return AE_NO_MEMORY;
878
        }
879
 
880
        /* Initialize the region with the default fill value */
881
 
882
        ACPI_MEMSET (RegionElement->Buffer, AcpiGbl_RegionFillValue, Length);
883
 
884
        RegionElement->Address      = BaseAddress;
885
        RegionElement->Length       = Length;
886
        RegionElement->SpaceId      = SpaceId;
887
        RegionElement->NextRegion   = NULL;
888
 
889
        /*
890
         * Increment the number of regions and put this one
891
         *  at the head of the list as it will probably get accessed
892
         *  more often anyway.
893
         */
894
        AeRegions.NumberOfRegions += 1;
895
 
896
        if (AeRegions.RegionList)
897
        {
898
            RegionElement->NextRegion = AeRegions.RegionList;
899
        }
900
 
901
        AeRegions.RegionList = RegionElement;
902
    }
903
 
904
    /*
905
     * Calculate the size of the memory copy
906
     */
907
    ByteWidth = (BitWidth / 8);
908
 
909
    if (BitWidth % 8)
910
    {
911
        ByteWidth += 1;
912
    }
913
 
914
    /*
915
     * The buffer exists and is pointed to by RegionElement.
916
     * We now need to verify the request is valid and perform the operation.
917
     *
918
     * NOTE: RegionElement->Length is in bytes, therefore it we compare against
919
     * ByteWidth (see above)
920
     */
921
    if (((UINT64) Address + ByteWidth) >
922
        ((UINT64)(RegionElement->Address) + RegionElement->Length))
923
    {
924
        ACPI_WARNING ((AE_INFO,
925
            "Request on [%4.4s] is beyond region limit Req-0x%X+0x%X, Base=0x%X, Len-0x%X",
926
            (RegionObject->Region.Node)->Name.Ascii, (UINT32) Address,
927
            ByteWidth, (UINT32)(RegionElement->Address),
928
            RegionElement->Length));
929
 
930
        return AE_AML_REGION_LIMIT;
931
    }
932
 
933
    /*
934
     * Get BufferValue to point to the "address" in the buffer
935
     */
936
    BufferValue = ((UINT8 *) RegionElement->Buffer +
937
                    ((UINT64) Address - (UINT64) RegionElement->Address));
938
 
939
DoFunction:
940
 
941
    /*
942
     * Perform a read or write to the buffer space
943
     */
944
    switch (Function)
945
    {
946
    case ACPI_READ:
947
        /*
948
         * Set the pointer Value to whatever is in the buffer
949
         */
950
        ACPI_MEMCPY (Value, BufferValue, ByteWidth);
951
        break;
952
 
953
    case ACPI_WRITE:
954
        /*
955
         * Write the contents of Value to the buffer
956
         */
957
        ACPI_MEMCPY (BufferValue, Value, ByteWidth);
958
        break;
959
 
960
    default:
961
        return AE_BAD_PARAMETER;
962
    }
963
    return AE_OK;
964
}
965