Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/acpica/components/events/evregion.c
48525 views
1
/******************************************************************************
2
*
3
* Module Name: evregion - Operation Region support
4
*
5
*****************************************************************************/
6
7
/******************************************************************************
8
*
9
* 1. Copyright Notice
10
*
11
* Some or all of this work - Copyright (c) 1999 - 2025, 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
* Alternatively, you may choose to be licensed under the terms of the
117
* following license:
118
*
119
* Redistribution and use in source and binary forms, with or without
120
* modification, are permitted provided that the following conditions
121
* are met:
122
* 1. Redistributions of source code must retain the above copyright
123
* notice, this list of conditions, and the following disclaimer,
124
* without modification.
125
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
126
* substantially similar to the "NO WARRANTY" disclaimer below
127
* ("Disclaimer") and any redistribution must be conditioned upon
128
* including a substantially similar Disclaimer requirement for further
129
* binary redistribution.
130
* 3. Neither the names of the above-listed copyright holders nor the names
131
* of any contributors may be used to endorse or promote products derived
132
* from this software without specific prior written permission.
133
*
134
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145
*
146
* Alternatively, you may choose to be licensed under the terms of the
147
* GNU General Public License ("GPL") version 2 as published by the Free
148
* Software Foundation.
149
*
150
*****************************************************************************/
151
152
#include <contrib/dev/acpica/include/acpi.h>
153
#include <contrib/dev/acpica/include/accommon.h>
154
#include <contrib/dev/acpica/include/acevents.h>
155
#include <contrib/dev/acpica/include/acnamesp.h>
156
#include <contrib/dev/acpica/include/acinterp.h>
157
158
#define _COMPONENT ACPI_EVENTS
159
ACPI_MODULE_NAME ("evregion")
160
161
162
extern UINT8 AcpiGbl_DefaultAddressSpaces[];
163
164
/* Local prototypes */
165
166
static void
167
AcpiEvExecuteOrphanRegMethod (
168
ACPI_NAMESPACE_NODE *DeviceNode,
169
ACPI_ADR_SPACE_TYPE SpaceId);
170
171
172
static ACPI_STATUS
173
AcpiEvRegRun (
174
ACPI_HANDLE ObjHandle,
175
UINT32 Level,
176
void *Context,
177
void **ReturnValue);
178
179
180
/*******************************************************************************
181
*
182
* FUNCTION: AcpiEvInitializeOpRegions
183
*
184
* PARAMETERS: None
185
*
186
* RETURN: Status
187
*
188
* DESCRIPTION: Execute _REG methods for all Operation Regions that have
189
* an installed default region handler.
190
*
191
******************************************************************************/
192
193
ACPI_STATUS
194
AcpiEvInitializeOpRegions (
195
void)
196
{
197
ACPI_STATUS Status;
198
UINT32 i;
199
200
201
ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
202
203
204
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
205
if (ACPI_FAILURE (Status))
206
{
207
return_ACPI_STATUS (Status);
208
}
209
210
/* Run the _REG methods for OpRegions in each default address space */
211
212
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
213
{
214
/*
215
* Make sure the installed handler is the DEFAULT handler. If not the
216
* default, the _REG methods will have already been run (when the
217
* handler was installed)
218
*/
219
if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,
220
AcpiGbl_DefaultAddressSpaces[i]))
221
{
222
AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
223
AcpiGbl_DefaultAddressSpaces[i], ACPI_REG_CONNECT);
224
}
225
}
226
227
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
228
return_ACPI_STATUS (Status);
229
}
230
231
232
/*******************************************************************************
233
*
234
* FUNCTION: AcpiEvAddressSpaceDispatch
235
*
236
* PARAMETERS: RegionObj - Internal region object
237
* FieldObj - Corresponding field. Can be NULL.
238
* Function - Read or Write operation
239
* RegionOffset - Where in the region to read or write
240
* BitWidth - Field width in bits (8, 16, 32, or 64)
241
* Value - Pointer to in or out value, must be
242
* a full 64-bit integer
243
*
244
* RETURN: Status
245
*
246
* DESCRIPTION: Dispatch an address space or operation region access to
247
* a previously installed handler.
248
*
249
* NOTE: During early initialization, we always install the default region
250
* handlers for Memory, I/O and PCI_Config. This ensures that these operation
251
* region address spaces are always available as per the ACPI specification.
252
* This is especially needed in order to support the execution of
253
* module-level AML code during loading of the ACPI tables.
254
*
255
******************************************************************************/
256
257
ACPI_STATUS
258
AcpiEvAddressSpaceDispatch (
259
ACPI_OPERAND_OBJECT *RegionObj,
260
ACPI_OPERAND_OBJECT *FieldObj,
261
UINT32 Function,
262
UINT32 RegionOffset,
263
UINT32 BitWidth,
264
UINT64 *Value)
265
{
266
ACPI_STATUS Status;
267
ACPI_ADR_SPACE_HANDLER Handler;
268
ACPI_ADR_SPACE_SETUP RegionSetup;
269
ACPI_OPERAND_OBJECT *HandlerDesc;
270
ACPI_OPERAND_OBJECT *RegionObj2;
271
void *RegionContext = NULL;
272
ACPI_CONNECTION_INFO *Context;
273
ACPI_MUTEX ContextMutex;
274
BOOLEAN ContextLocked;
275
ACPI_PHYSICAL_ADDRESS Address;
276
277
278
ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
279
280
281
RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
282
if (!RegionObj2)
283
{
284
return_ACPI_STATUS (AE_NOT_EXIST);
285
}
286
287
/* Ensure that there is a handler associated with this region */
288
289
HandlerDesc = RegionObj->Region.Handler;
290
if (!HandlerDesc)
291
{
292
ACPI_ERROR ((AE_INFO,
293
"No handler for Region [%4.4s] (%p) [%s]",
294
AcpiUtGetNodeName (RegionObj->Region.Node),
295
RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
296
297
return_ACPI_STATUS (AE_NOT_EXIST);
298
}
299
300
Context = HandlerDesc->AddressSpace.Context;
301
ContextMutex = HandlerDesc->AddressSpace.ContextMutex;
302
ContextLocked = FALSE;
303
304
/*
305
* It may be the case that the region has never been initialized.
306
* Some types of regions require special init code
307
*/
308
if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
309
{
310
/* This region has not been initialized yet, do it */
311
312
RegionSetup = HandlerDesc->AddressSpace.Setup;
313
if (!RegionSetup)
314
{
315
/* No initialization routine, exit with error */
316
317
ACPI_ERROR ((AE_INFO,
318
"No init routine for region(%p) [%s]",
319
RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
320
return_ACPI_STATUS (AE_NOT_EXIST);
321
}
322
323
if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_COMM)
324
{
325
ACPI_PCC_INFO *Ctx = HandlerDesc->AddressSpace.Context;
326
327
Ctx->InternalBuffer = FieldObj->Field.InternalPccBuffer;
328
Ctx->Length = (UINT16) RegionObj->Region.Length;
329
Ctx->SubspaceId = (UINT8) RegionObj->Region.Address;
330
}
331
332
if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE)
333
{
334
ACPI_FFH_INFO *Ctx = HandlerDesc->AddressSpace.Context;
335
336
Ctx->Length = RegionObj->Region.Length;
337
Ctx->Offset = RegionObj->Region.Address;
338
}
339
340
/*
341
* We must exit the interpreter because the region setup will
342
* potentially execute control methods (for example, the _REG method
343
* for this region)
344
*/
345
AcpiExExitInterpreter ();
346
347
Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
348
Context, &RegionContext);
349
350
/* Re-enter the interpreter */
351
352
AcpiExEnterInterpreter ();
353
354
/* Check for failure of the Region Setup */
355
356
if (ACPI_FAILURE (Status))
357
{
358
ACPI_EXCEPTION ((AE_INFO, Status,
359
"During region initialization: [%s]",
360
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
361
return_ACPI_STATUS (Status);
362
}
363
364
/* Region initialization may have been completed by RegionSetup */
365
366
if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
367
{
368
RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
369
370
/*
371
* Save the returned context for use in all accesses to
372
* the handler for this particular region
373
*/
374
if (!(RegionObj2->Extra.RegionContext))
375
{
376
RegionObj2->Extra.RegionContext = RegionContext;
377
}
378
}
379
}
380
381
/* We have everything we need, we can invoke the address space handler */
382
383
Handler = HandlerDesc->AddressSpace.Handler;
384
Address = (RegionObj->Region.Address + RegionOffset);
385
386
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
387
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
388
&RegionObj->Region.Handler->AddressSpace, Handler,
389
ACPI_FORMAT_UINT64 (Address),
390
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
391
392
if (!(HandlerDesc->AddressSpace.HandlerFlags &
393
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
394
{
395
/*
396
* For handlers other than the default (supplied) handlers, we must
397
* exit the interpreter because the handler *might* block -- we don't
398
* know what it will do, so we can't hold the lock on the interpreter.
399
*/
400
AcpiExExitInterpreter();
401
}
402
403
/*
404
* Special handling for GenericSerialBus and GeneralPurposeIo:
405
* There are three extra parameters that must be passed to the
406
* handler via the context:
407
* 1) Connection buffer, a resource template from Connection() op
408
* 2) Length of the above buffer
409
* 3) Actual access length from the AccessAs() op
410
*
411
* Since we pass these extra parameters via the context, which is
412
* shared between threads, we must lock the context to avoid these
413
* parameters being changed from another thread before the handler
414
* has completed running.
415
*
416
* In addition, for GeneralPurposeIo, the Address and BitWidth fields
417
* are defined as follows:
418
* 1) Address is the pin number index of the field (bit offset from
419
* the previous Connection)
420
* 2) BitWidth is the actual bit length of the field (number of pins)
421
*/
422
if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS ||
423
RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) &&
424
Context &&
425
FieldObj)
426
{
427
428
Status = AcpiOsAcquireMutex (ContextMutex, ACPI_WAIT_FOREVER);
429
if (ACPI_FAILURE (Status))
430
{
431
goto ReEnterInterpreter;
432
}
433
434
ContextLocked = TRUE;
435
436
/* Get the Connection (ResourceTemplate) buffer */
437
438
Context->Connection = FieldObj->Field.ResourceBuffer;
439
Context->Length = FieldObj->Field.ResourceLength;
440
Context->AccessLength = FieldObj->Field.AccessLength;
441
442
if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)
443
{
444
Address = FieldObj->Field.PinNumberIndex;
445
BitWidth = FieldObj->Field.BitLength;
446
}
447
}
448
449
/* Call the handler */
450
451
Status = Handler (Function, Address, BitWidth, Value, Context,
452
RegionObj2->Extra.RegionContext);
453
454
if (ContextLocked)
455
{
456
AcpiOsReleaseMutex (ContextMutex);
457
}
458
459
if (ACPI_FAILURE (Status))
460
{
461
ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
462
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
463
464
/*
465
* Special case for an EC timeout. These are seen so frequently
466
* that an additional error message is helpful
467
*/
468
if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) &&
469
(Status == AE_TIME))
470
{
471
ACPI_ERROR ((AE_INFO,
472
"Timeout from EC hardware or EC device driver"));
473
}
474
}
475
476
ReEnterInterpreter:
477
if (!(HandlerDesc->AddressSpace.HandlerFlags &
478
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
479
{
480
/*
481
* We just returned from a non-default handler, we must re-enter the
482
* interpreter
483
*/
484
AcpiExEnterInterpreter ();
485
}
486
487
return_ACPI_STATUS (Status);
488
}
489
490
491
/*******************************************************************************
492
*
493
* FUNCTION: AcpiEvDetachRegion
494
*
495
* PARAMETERS: RegionObj - Region Object
496
* AcpiNsIsLocked - Namespace Region Already Locked?
497
*
498
* RETURN: None
499
*
500
* DESCRIPTION: Break the association between the handler and the region
501
* this is a two way association.
502
*
503
******************************************************************************/
504
505
void
506
AcpiEvDetachRegion (
507
ACPI_OPERAND_OBJECT *RegionObj,
508
BOOLEAN AcpiNsIsLocked)
509
{
510
ACPI_OPERAND_OBJECT *HandlerObj;
511
ACPI_OPERAND_OBJECT *ObjDesc;
512
ACPI_OPERAND_OBJECT *StartDesc;
513
ACPI_OPERAND_OBJECT **LastObjPtr;
514
ACPI_ADR_SPACE_SETUP RegionSetup;
515
void **RegionContext;
516
ACPI_OPERAND_OBJECT *RegionObj2;
517
ACPI_STATUS Status;
518
519
520
ACPI_FUNCTION_TRACE (EvDetachRegion);
521
522
523
RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
524
if (!RegionObj2)
525
{
526
return_VOID;
527
}
528
RegionContext = &RegionObj2->Extra.RegionContext;
529
530
/* Get the address handler from the region object */
531
532
HandlerObj = RegionObj->Region.Handler;
533
if (!HandlerObj)
534
{
535
/* This region has no handler, all done */
536
537
return_VOID;
538
}
539
540
/* Find this region in the handler's list */
541
542
ObjDesc = HandlerObj->AddressSpace.RegionList;
543
StartDesc = ObjDesc;
544
LastObjPtr = &HandlerObj->AddressSpace.RegionList;
545
546
while (ObjDesc)
547
{
548
/* Is this the correct Region? */
549
550
if (ObjDesc == RegionObj)
551
{
552
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
553
"Removing Region %p from address handler %p\n",
554
RegionObj, HandlerObj));
555
556
/* This is it, remove it from the handler's list */
557
558
*LastObjPtr = ObjDesc->Region.Next;
559
ObjDesc->Region.Next = NULL; /* Must clear field */
560
561
if (AcpiNsIsLocked)
562
{
563
Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
564
if (ACPI_FAILURE (Status))
565
{
566
return_VOID;
567
}
568
}
569
570
/* Now stop region accesses by executing the _REG method */
571
572
Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT);
573
if (ACPI_FAILURE (Status))
574
{
575
ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
576
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
577
}
578
579
if (AcpiNsIsLocked)
580
{
581
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
582
if (ACPI_FAILURE (Status))
583
{
584
return_VOID;
585
}
586
}
587
588
/*
589
* If the region has been activated, call the setup handler with
590
* the deactivate notification
591
*/
592
if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
593
{
594
RegionSetup = HandlerObj->AddressSpace.Setup;
595
Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
596
HandlerObj->AddressSpace.Context, RegionContext);
597
598
/*
599
* RegionContext should have been released by the deactivate
600
* operation. We don't need access to it anymore here.
601
*/
602
if (RegionContext)
603
{
604
*RegionContext = NULL;
605
}
606
607
/* Init routine may fail, Just ignore errors */
608
609
if (ACPI_FAILURE (Status))
610
{
611
ACPI_EXCEPTION ((AE_INFO, Status,
612
"from region handler - deactivate, [%s]",
613
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
614
}
615
616
RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
617
}
618
619
/*
620
* Remove handler reference in the region
621
*
622
* NOTE: this doesn't mean that the region goes away, the region
623
* is just inaccessible as indicated to the _REG method
624
*
625
* If the region is on the handler's list, this must be the
626
* region's handler
627
*/
628
RegionObj->Region.Handler = NULL;
629
AcpiUtRemoveReference (HandlerObj);
630
631
return_VOID;
632
}
633
634
/* Walk the linked list of handlers */
635
636
LastObjPtr = &ObjDesc->Region.Next;
637
ObjDesc = ObjDesc->Region.Next;
638
639
/* Prevent infinite loop if list is corrupted */
640
641
if (ObjDesc == StartDesc)
642
{
643
ACPI_ERROR ((AE_INFO,
644
"Circular handler list in region object %p",
645
RegionObj));
646
return_VOID;
647
}
648
}
649
650
/* If we get here, the region was not in the handler's region list */
651
652
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
653
"Cannot remove region %p from address handler %p\n",
654
RegionObj, HandlerObj));
655
656
return_VOID;
657
}
658
659
660
/*******************************************************************************
661
*
662
* FUNCTION: AcpiEvAttachRegion
663
*
664
* PARAMETERS: HandlerObj - Handler Object
665
* RegionObj - Region Object
666
* AcpiNsIsLocked - Namespace Region Already Locked?
667
*
668
* RETURN: None
669
*
670
* DESCRIPTION: Create the association between the handler and the region
671
* this is a two way association.
672
*
673
******************************************************************************/
674
675
ACPI_STATUS
676
AcpiEvAttachRegion (
677
ACPI_OPERAND_OBJECT *HandlerObj,
678
ACPI_OPERAND_OBJECT *RegionObj,
679
BOOLEAN AcpiNsIsLocked)
680
{
681
682
ACPI_FUNCTION_TRACE (EvAttachRegion);
683
684
685
/* Install the region's handler */
686
687
if (RegionObj->Region.Handler)
688
{
689
return_ACPI_STATUS (AE_ALREADY_EXISTS);
690
}
691
692
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
693
"Adding Region [%4.4s] %p to address handler %p [%s]\n",
694
AcpiUtGetNodeName (RegionObj->Region.Node),
695
RegionObj, HandlerObj,
696
AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
697
698
/* Link this region to the front of the handler's list */
699
700
RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
701
HandlerObj->AddressSpace.RegionList = RegionObj;
702
RegionObj->Region.Handler = HandlerObj;
703
AcpiUtAddReference (HandlerObj);
704
705
return_ACPI_STATUS (AE_OK);
706
}
707
708
709
/*******************************************************************************
710
*
711
* FUNCTION: AcpiEvExecuteRegMethod
712
*
713
* PARAMETERS: RegionObj - Region object
714
* Function - Passed to _REG: On (1) or Off (0)
715
*
716
* RETURN: Status
717
*
718
* DESCRIPTION: Execute _REG method for a region
719
*
720
******************************************************************************/
721
722
ACPI_STATUS
723
AcpiEvExecuteRegMethod (
724
ACPI_OPERAND_OBJECT *RegionObj,
725
UINT32 Function)
726
{
727
ACPI_EVALUATE_INFO *Info;
728
ACPI_OPERAND_OBJECT *Args[3];
729
ACPI_OPERAND_OBJECT *RegionObj2;
730
const ACPI_NAME *RegNamePtr = ACPI_CAST_PTR (ACPI_NAME, METHOD_NAME__REG);
731
ACPI_NAMESPACE_NODE *MethodNode;
732
ACPI_NAMESPACE_NODE *Node;
733
ACPI_STATUS Status;
734
735
736
ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
737
738
739
if (!AcpiGbl_NamespaceInitialized ||
740
RegionObj->Region.Handler == NULL)
741
{
742
return_ACPI_STATUS (AE_OK);
743
}
744
745
RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
746
if (!RegionObj2)
747
{
748
return_ACPI_STATUS (AE_NOT_EXIST);
749
}
750
751
/*
752
* Find any "_REG" method associated with this region definition.
753
* The method should always be updated as this function may be
754
* invoked after a namespace change.
755
*/
756
Node = RegionObj->Region.Node->Parent;
757
Status = AcpiNsSearchOneScope (
758
*RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode);
759
if (ACPI_SUCCESS (Status))
760
{
761
/*
762
* The _REG method is optional and there can be only one per
763
* region definition. This will be executed when the handler is
764
* attached or removed.
765
*/
766
RegionObj2->Extra.Method_REG = MethodNode;
767
}
768
if (RegionObj2->Extra.Method_REG == NULL)
769
{
770
return_ACPI_STATUS (AE_OK);
771
}
772
773
/* _REG(DISCONNECT) should be paired with _REG(CONNECT) */
774
775
if ((Function == ACPI_REG_CONNECT &&
776
RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED) ||
777
(Function == ACPI_REG_DISCONNECT &&
778
!(RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED)))
779
{
780
return_ACPI_STATUS (AE_OK);
781
}
782
783
/* Allocate and initialize the evaluation information block */
784
785
Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
786
if (!Info)
787
{
788
return_ACPI_STATUS (AE_NO_MEMORY);
789
}
790
791
Info->PrefixNode = RegionObj2->Extra.Method_REG;
792
Info->RelativePathname = NULL;
793
Info->Parameters = Args;
794
Info->Flags = ACPI_IGNORE_RETURN_VALUE;
795
796
/*
797
* The _REG method has two arguments:
798
*
799
* Arg0 - Integer:
800
* Operation region space ID Same value as RegionObj->Region.SpaceId
801
*
802
* Arg1 - Integer:
803
* connection status 1 for connecting the handler, 0 for disconnecting
804
* the handler (Passed as a parameter)
805
*/
806
Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
807
if (!Args[0])
808
{
809
Status = AE_NO_MEMORY;
810
goto Cleanup1;
811
}
812
813
Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
814
if (!Args[1])
815
{
816
Status = AE_NO_MEMORY;
817
goto Cleanup2;
818
}
819
820
Args[2] = NULL; /* Terminate list */
821
822
/* Execute the method, no return value */
823
824
ACPI_DEBUG_EXEC (
825
AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
826
827
Status = AcpiNsEvaluate (Info);
828
AcpiUtRemoveReference (Args[1]);
829
830
if (ACPI_FAILURE (Status))
831
{
832
goto Cleanup2;
833
}
834
835
if (Function == ACPI_REG_CONNECT)
836
{
837
RegionObj->Common.Flags |= AOPOBJ_REG_CONNECTED;
838
}
839
else
840
{
841
RegionObj->Common.Flags &= ~AOPOBJ_REG_CONNECTED;
842
}
843
844
Cleanup2:
845
AcpiUtRemoveReference (Args[0]);
846
847
Cleanup1:
848
ACPI_FREE (Info);
849
return_ACPI_STATUS (Status);
850
}
851
852
853
/*******************************************************************************
854
*
855
* FUNCTION: AcpiEvExecuteRegMethods
856
*
857
* PARAMETERS: Node - Namespace node for the device
858
* SpaceId - The address space ID
859
* Function - Passed to _REG: On (1) or Off (0)
860
*
861
* RETURN: None
862
*
863
* DESCRIPTION: Run all _REG methods for the input Space ID;
864
* Note: assumes namespace is locked, or system init time.
865
*
866
******************************************************************************/
867
868
void
869
AcpiEvExecuteRegMethods (
870
ACPI_NAMESPACE_NODE *Node,
871
ACPI_ADR_SPACE_TYPE SpaceId,
872
UINT32 Function)
873
{
874
ACPI_REG_WALK_INFO Info;
875
876
877
ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
878
879
/*
880
* These address spaces do not need a call to _REG, since the ACPI
881
* specification defines them as: "must always be accessible". Since
882
* they never change state (never become unavailable), no need to ever
883
* call _REG on them. Also, a DataTable is not a "real" address space,
884
* so do not call _REG. September 2018.
885
*/
886
if ((SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||
887
(SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) ||
888
(SpaceId == ACPI_ADR_SPACE_DATA_TABLE))
889
{
890
return_VOID;
891
}
892
893
Info.SpaceId = SpaceId;
894
Info.Function = Function;
895
Info.RegRunCount = 0;
896
897
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,
898
" Running _REG methods for SpaceId %s\n",
899
AcpiUtGetRegionName (Info.SpaceId)));
900
901
/*
902
* Run all _REG methods for all Operation Regions for this space ID. This
903
* is a separate walk in order to handle any interdependencies between
904
* regions and _REG methods. (i.e. handlers must be installed for all
905
* regions of this Space ID before we can run any _REG methods)
906
*/
907
(void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
908
ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, &Info, NULL);
909
910
/*
911
* Special case for EC and GPIO: handle "orphan" _REG methods with
912
* no region.
913
*/
914
if (SpaceId == ACPI_ADR_SPACE_EC || SpaceId == ACPI_ADR_SPACE_GPIO)
915
{
916
AcpiEvExecuteOrphanRegMethod (Node, SpaceId);
917
}
918
919
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,
920
" Executed %u _REG methods for SpaceId %s\n",
921
Info.RegRunCount, AcpiUtGetRegionName (Info.SpaceId)));
922
923
return_VOID;
924
}
925
926
927
/*******************************************************************************
928
*
929
* FUNCTION: AcpiEvRegRun
930
*
931
* PARAMETERS: WalkNamespace callback
932
*
933
* DESCRIPTION: Run _REG method for region objects of the requested spaceID
934
*
935
******************************************************************************/
936
937
static ACPI_STATUS
938
AcpiEvRegRun (
939
ACPI_HANDLE ObjHandle,
940
UINT32 Level,
941
void *Context,
942
void **ReturnValue)
943
{
944
ACPI_OPERAND_OBJECT *ObjDesc;
945
ACPI_NAMESPACE_NODE *Node;
946
ACPI_STATUS Status;
947
ACPI_REG_WALK_INFO *Info;
948
949
950
Info = ACPI_CAST_PTR (ACPI_REG_WALK_INFO, Context);
951
952
/* Convert and validate the device handle */
953
954
Node = AcpiNsValidateHandle (ObjHandle);
955
if (!Node)
956
{
957
return (AE_BAD_PARAMETER);
958
}
959
960
/*
961
* We only care about regions and objects that are allowed to have
962
* address space handlers
963
*/
964
if ((Node->Type != ACPI_TYPE_REGION) &&
965
(Node != AcpiGbl_RootNode))
966
{
967
return (AE_OK);
968
}
969
970
/* Check for an existing internal object */
971
972
ObjDesc = AcpiNsGetAttachedObject (Node);
973
if (!ObjDesc)
974
{
975
/* No object, just exit */
976
977
return (AE_OK);
978
}
979
980
/* Object is a Region */
981
982
if (ObjDesc->Region.SpaceId != Info->SpaceId)
983
{
984
/* This region is for a different address space, just ignore it */
985
986
return (AE_OK);
987
}
988
989
Info->RegRunCount++;
990
Status = AcpiEvExecuteRegMethod (ObjDesc, Info->Function);
991
return (Status);
992
}
993
994
995
/*******************************************************************************
996
*
997
* FUNCTION: AcpiEvExecuteOrphanRegMethod
998
*
999
* PARAMETERS: DeviceNode - Namespace node for an ACPI device
1000
* SpaceId - The address space ID
1001
*
1002
* RETURN: None
1003
*
1004
* DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI
1005
* device. This is a _REG method that has no corresponding region
1006
* within the device's scope. ACPI tables depending on these
1007
* "orphan" _REG methods have been seen for both EC and GPIO
1008
* Operation Regions. Presumably the Windows ACPI implementation
1009
* always calls the _REG method independent of the presence of
1010
* an actual Operation Region with the correct address space ID.
1011
*
1012
* MUTEX: Assumes the namespace is locked
1013
*
1014
******************************************************************************/
1015
1016
static void
1017
AcpiEvExecuteOrphanRegMethod (
1018
ACPI_NAMESPACE_NODE *DeviceNode,
1019
ACPI_ADR_SPACE_TYPE SpaceId)
1020
{
1021
ACPI_HANDLE RegMethod;
1022
ACPI_NAMESPACE_NODE *NextNode;
1023
ACPI_STATUS Status;
1024
ACPI_OBJECT_LIST Args;
1025
ACPI_OBJECT Objects[2];
1026
1027
1028
ACPI_FUNCTION_TRACE (EvExecuteOrphanRegMethod);
1029
1030
1031
if (!DeviceNode)
1032
{
1033
return_VOID;
1034
}
1035
1036
/* Namespace is currently locked, must release */
1037
1038
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1039
1040
/* Get a handle to a _REG method immediately under the EC device */
1041
1042
Status = AcpiGetHandle (DeviceNode, METHOD_NAME__REG, &RegMethod);
1043
if (ACPI_FAILURE (Status))
1044
{
1045
goto Exit; /* There is no _REG method present */
1046
}
1047
1048
/*
1049
* Execute the _REG method only if there is no Operation Region in
1050
* this scope with the Embedded Controller space ID. Otherwise, it
1051
* will already have been executed. Note, this allows for Regions
1052
* with other space IDs to be present; but the code below will then
1053
* execute the _REG method with the EmbeddedControl SpaceID argument.
1054
*/
1055
NextNode = AcpiNsGetNextNode (DeviceNode, NULL);
1056
while (NextNode)
1057
{
1058
if ((NextNode->Type == ACPI_TYPE_REGION) &&
1059
(NextNode->Object) &&
1060
(NextNode->Object->Region.SpaceId == SpaceId))
1061
{
1062
goto Exit; /* Do not execute the _REG */
1063
}
1064
1065
NextNode = AcpiNsGetNextNode (DeviceNode, NextNode);
1066
}
1067
1068
/* Evaluate the _REG(SpaceId,Connect) method */
1069
1070
Args.Count = 2;
1071
Args.Pointer = Objects;
1072
Objects[0].Type = ACPI_TYPE_INTEGER;
1073
Objects[0].Integer.Value = SpaceId;
1074
Objects[1].Type = ACPI_TYPE_INTEGER;
1075
Objects[1].Integer.Value = ACPI_REG_CONNECT;
1076
1077
(void) AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);
1078
1079
Exit:
1080
/* We ignore all errors from above, don't care */
1081
1082
(void) AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1083
return_VOID;
1084
}
1085
1086