ReactOS 0.4.15-dev-7842-g558ab78
exregion.c
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Module Name: exregion - ACPI default OpRegion (address space) handlers
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2022, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include "acpi.h"
45#include "accommon.h"
46#include "acinterp.h"
47
48
49#define _COMPONENT ACPI_EXECUTER
50 ACPI_MODULE_NAME ("exregion")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: AcpiExSystemMemorySpaceHandler
56 *
57 * PARAMETERS: Function - Read or Write operation
58 * Address - Where in the space to read or write
59 * BitWidth - Field width in bits (8, 16, or 32)
60 * Value - Pointer to in or out value
61 * HandlerContext - Pointer to Handler's context
62 * RegionContext - Pointer to context specific to the
63 * accessed region
64 *
65 * RETURN: Status
66 *
67 * DESCRIPTION: Handler for the System Memory address space (Op Region)
68 *
69 ******************************************************************************/
70
74 ACPI_PHYSICAL_ADDRESS Address,
75 UINT32 BitWidth,
77 void *HandlerContext,
78 void *RegionContext)
79{
81 void *LogicalAddrPtr = NULL;
82 ACPI_MEM_SPACE_CONTEXT *MemInfo = RegionContext;
83 ACPI_MEM_MAPPING *Mm = MemInfo->CurMm;
85 ACPI_SIZE MapLength;
86 ACPI_SIZE PageBoundaryMapLength;
87#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
89#endif
90
91
92 ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler);
93
94
95 /* Validate and translate the bit width */
96
97 switch (BitWidth)
98 {
99 case 8:
100
101 Length = 1;
102 break;
103
104 case 16:
105
106 Length = 2;
107 break;
108
109 case 32:
110
111 Length = 4;
112 break;
113
114 case 64:
115
116 Length = 8;
117 break;
118
119 default:
120
121 ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %u",
122 BitWidth));
124 }
125
126#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
127 /*
128 * Hardware does not support non-aligned data transfers, we must verify
129 * the request.
130 */
132 if (Remainder != 0)
133 {
135 }
136#endif
137
138 /*
139 * Does the request fit into the cached memory mapping?
140 * Is 1) Address below the current mapping? OR
141 * 2) Address beyond the current mapping?
142 */
143 if (!Mm || (Address < Mm->PhysicalAddress) ||
144 ((UINT64) Address + Length > (UINT64) Mm->PhysicalAddress + Mm->Length))
145 {
146 /*
147 * The request cannot be resolved by the current memory mapping.
148 *
149 * Look for an existing saved mapping covering the address range
150 * at hand. If found, save it as the current one and carry out
151 * the access.
152 */
153 for (Mm = MemInfo->FirstMm; Mm; Mm = Mm->NextMm)
154 {
155 if (Mm == MemInfo->CurMm)
156 {
157 continue;
158 }
159
160 if (Address < Mm->PhysicalAddress)
161 {
162 continue;
163 }
164
165 if ((UINT64) Address + Length > (UINT64) Mm->PhysicalAddress + Mm->Length)
166 {
167 continue;
168 }
169
170 MemInfo->CurMm = Mm;
171 goto access;
172 }
173
174 /* Create a new mappings list entry */
175
176 Mm = ACPI_ALLOCATE_ZEROED(sizeof(*Mm));
177 if (!Mm)
178 {
180 "Unable to save memory mapping at 0x%8.8X%8.8X, size %u",
183 }
184
185 /*
186 * October 2009: Attempt to map from the requested address to the
187 * end of the region. However, we will never map more than one
188 * page, nor will we cross a page boundary.
189 */
190 MapLength = (ACPI_SIZE)
191 ((MemInfo->Address + MemInfo->Length) - Address);
192
193 /*
194 * If mapping the entire remaining portion of the region will cross
195 * a page boundary, just map up to the page boundary, do not cross.
196 * On some systems, crossing a page boundary while mapping regions
197 * can cause warnings if the pages have different attributes
198 * due to resource management.
199 *
200 * This has the added benefit of constraining a single mapping to
201 * one page, which is similar to the original code that used a 4k
202 * maximum window.
203 */
204 PageBoundaryMapLength = (ACPI_SIZE)
206 if (PageBoundaryMapLength == 0)
207 {
208 PageBoundaryMapLength = ACPI_DEFAULT_PAGE_SIZE;
209 }
210
211 if (MapLength > PageBoundaryMapLength)
212 {
213 MapLength = PageBoundaryMapLength;
214 }
215
216 /* Create a new mapping starting at the address given */
217
218 LogicalAddrPtr = AcpiOsMapMemory(Address, MapLength);
219 if (!LogicalAddrPtr)
220 {
222 "Could not map memory at 0x%8.8X%8.8X, size %u",
223 ACPI_FORMAT_UINT64 (Address), (UINT32) MapLength));
224 ACPI_FREE(Mm);
226 }
227
228 /* Save the physical address and mapping size */
229
230 Mm->LogicalAddress = LogicalAddrPtr;
232 Mm->Length = MapLength;
233
234 /*
235 * Add the new entry to the mappigs list and save it as the
236 * current mapping.
237 */
238 Mm->NextMm = MemInfo->FirstMm;
239 MemInfo->FirstMm = Mm;
240 MemInfo->CurMm = Mm;
241 }
242
243access:
244 /*
245 * Generate a logical pointer corresponding to the address we want to
246 * access
247 */
248 LogicalAddrPtr = Mm->LogicalAddress +
250
252 "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
253 BitWidth, Function, ACPI_FORMAT_UINT64 (Address)));
254
255 /*
256 * Perform the memory read or write
257 *
258 * Note: For machines that do not support non-aligned transfers, the target
259 * address was checked for alignment above. We do not attempt to break the
260 * transfer up into smaller (byte-size) chunks because the AML specifically
261 * asked for a transfer width that the hardware may require.
262 */
263 switch (Function)
264 {
265 case ACPI_READ:
266
267 *Value = 0;
268 switch (BitWidth)
269 {
270 case 8:
271
272 *Value = (UINT64) ACPI_GET8 (LogicalAddrPtr);
273 break;
274
275 case 16:
276
277 *Value = (UINT64) ACPI_GET16 (LogicalAddrPtr);
278 break;
279
280 case 32:
281
282 *Value = (UINT64) ACPI_GET32 (LogicalAddrPtr);
283 break;
284
285 case 64:
286
287 *Value = (UINT64) ACPI_GET64 (LogicalAddrPtr);
288 break;
289
290 default:
291
292 /* BitWidth was already validated */
293
294 break;
295 }
296 break;
297
298 case ACPI_WRITE:
299
300 switch (BitWidth)
301 {
302 case 8:
303
304 ACPI_SET8 (LogicalAddrPtr, *Value);
305 break;
306
307 case 16:
308
309 ACPI_SET16 (LogicalAddrPtr, *Value);
310 break;
311
312 case 32:
313
314 ACPI_SET32 (LogicalAddrPtr, *Value);
315 break;
316
317 case 64:
318
319 ACPI_SET64 (LogicalAddrPtr, *Value);
320 break;
321
322 default:
323
324 /* BitWidth was already validated */
325
326 break;
327 }
328 break;
329
330 default:
331
333 break;
334 }
335
337}
338
339
340/*******************************************************************************
341 *
342 * FUNCTION: AcpiExSystemIoSpaceHandler
343 *
344 * PARAMETERS: Function - Read or Write operation
345 * Address - Where in the space to read or write
346 * BitWidth - Field width in bits (8, 16, or 32)
347 * Value - Pointer to in or out value
348 * HandlerContext - Pointer to Handler's context
349 * RegionContext - Pointer to context specific to the
350 * accessed region
351 *
352 * RETURN: Status
353 *
354 * DESCRIPTION: Handler for the System IO address space (Op Region)
355 *
356 ******************************************************************************/
357
361 ACPI_PHYSICAL_ADDRESS Address,
362 UINT32 BitWidth,
363 UINT64 *Value,
364 void *HandlerContext,
365 void *RegionContext)
366{
368 UINT32 Value32;
369
370
371 ACPI_FUNCTION_TRACE (ExSystemIoSpaceHandler);
372
373
375 "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
376 BitWidth, Function, ACPI_FORMAT_UINT64 (Address)));
377
378 /* Decode the function parameter */
379
380 switch (Function)
381 {
382 case ACPI_READ:
383
384 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) Address,
385 &Value32, BitWidth);
386 *Value = Value32;
387 break;
388
389 case ACPI_WRITE:
390
391 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) Address,
392 (UINT32) *Value, BitWidth);
393 break;
394
395 default:
396
398 break;
399 }
400
402}
403
404
405/*******************************************************************************
406 *
407 * FUNCTION: AcpiExPciConfigSpaceHandler
408 *
409 * PARAMETERS: Function - Read or Write operation
410 * Address - Where in the space to read or write
411 * BitWidth - Field width in bits (8, 16, or 32)
412 * Value - Pointer to in or out value
413 * HandlerContext - Pointer to Handler's context
414 * RegionContext - Pointer to context specific to the
415 * accessed region
416 *
417 * RETURN: Status
418 *
419 * DESCRIPTION: Handler for the PCI Config address space (Op Region)
420 *
421 ******************************************************************************/
422
426 ACPI_PHYSICAL_ADDRESS Address,
427 UINT32 BitWidth,
428 UINT64 *Value,
429 void *HandlerContext,
430 void *RegionContext)
431{
433 ACPI_PCI_ID *PciId;
434 UINT16 PciRegister;
435
436
437 ACPI_FUNCTION_TRACE (ExPciConfigSpaceHandler);
438
439
440 /*
441 * The arguments to AcpiOs(Read|Write)PciConfiguration are:
442 *
443 * PciSegment is the PCI bus segment range 0-31
444 * PciBus is the PCI bus number range 0-255
445 * PciDevice is the PCI device number range 0-31
446 * PciFunction is the PCI device function number
447 * PciRegister is the Config space register range 0-255 bytes
448 *
449 * Value - input value for write, output address for read
450 *
451 */
452 PciId = (ACPI_PCI_ID *) RegionContext;
453 PciRegister = (UINT16) (UINT32) Address;
454
456 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) "
457 "Dev(%04x) Func(%04x) Reg(%04x)\n",
458 Function, BitWidth, PciId->Segment, PciId->Bus, PciId->Device,
459 PciId->Function, PciRegister));
460
461 switch (Function)
462 {
463 case ACPI_READ:
464
465 *Value = 0;
467 PciId, PciRegister, Value, BitWidth);
468 break;
469
470 case ACPI_WRITE:
471
473 PciId, PciRegister, *Value, BitWidth);
474 break;
475
476 default:
477
479 break;
480 }
481
483}
484
485
486/*******************************************************************************
487 *
488 * FUNCTION: AcpiExCmosSpaceHandler
489 *
490 * PARAMETERS: Function - Read or Write operation
491 * Address - Where in the space to read or write
492 * BitWidth - Field width in bits (8, 16, or 32)
493 * Value - Pointer to in or out value
494 * HandlerContext - Pointer to Handler's context
495 * RegionContext - Pointer to context specific to the
496 * accessed region
497 *
498 * RETURN: Status
499 *
500 * DESCRIPTION: Handler for the CMOS address space (Op Region)
501 *
502 ******************************************************************************/
503
507 ACPI_PHYSICAL_ADDRESS Address,
508 UINT32 BitWidth,
509 UINT64 *Value,
510 void *HandlerContext,
511 void *RegionContext)
512{
514
515
516 ACPI_FUNCTION_TRACE (ExCmosSpaceHandler);
517
518
520}
521
522
523/*******************************************************************************
524 *
525 * FUNCTION: AcpiExPciBarSpaceHandler
526 *
527 * PARAMETERS: Function - Read or Write operation
528 * Address - Where in the space to read or write
529 * BitWidth - Field width in bits (8, 16, or 32)
530 * Value - Pointer to in or out value
531 * HandlerContext - Pointer to Handler's context
532 * RegionContext - Pointer to context specific to the
533 * accessed region
534 *
535 * RETURN: Status
536 *
537 * DESCRIPTION: Handler for the PCI BarTarget address space (Op Region)
538 *
539 ******************************************************************************/
540
544 ACPI_PHYSICAL_ADDRESS Address,
545 UINT32 BitWidth,
546 UINT64 *Value,
547 void *HandlerContext,
548 void *RegionContext)
549{
551
552
553 ACPI_FUNCTION_TRACE (ExPciBarSpaceHandler);
554
555
557}
558
559
560/*******************************************************************************
561 *
562 * FUNCTION: AcpiExDataTableSpaceHandler
563 *
564 * PARAMETERS: Function - Read or Write operation
565 * Address - Where in the space to read or write
566 * BitWidth - Field width in bits (8, 16, or 32)
567 * Value - Pointer to in or out value
568 * HandlerContext - Pointer to Handler's context
569 * RegionContext - Pointer to context specific to the
570 * accessed region
571 *
572 * RETURN: Status
573 *
574 * DESCRIPTION: Handler for the Data Table address space (Op Region)
575 *
576 ******************************************************************************/
577
581 ACPI_PHYSICAL_ADDRESS Address,
582 UINT32 BitWidth,
583 UINT64 *Value,
584 void *HandlerContext,
585 void *RegionContext)
586{
588 char *Pointer;
589
590
591 ACPI_FUNCTION_TRACE (ExDataTableSpaceHandler);
592
593
594 Mapping = (ACPI_DATA_TABLE_MAPPING *) RegionContext;
595 Pointer = ACPI_CAST_PTR (char, Mapping->Pointer) +
596 (Address - ACPI_PTR_TO_PHYSADDR (Mapping->Pointer));
597
598 /*
599 * Perform the memory read or write. The BitWidth was already
600 * validated.
601 */
602 switch (Function)
603 {
604 case ACPI_READ:
605
606 memcpy (ACPI_CAST_PTR (char, Value), Pointer, ACPI_DIV_8 (BitWidth));
607 break;
608
609 case ACPI_WRITE:
610
611 memcpy (Pointer, ACPI_CAST_PTR (char, Value), ACPI_DIV_8 (BitWidth));
612 break;
613
614 default:
615
617 }
618
620}
unsigned short UINT16
unsigned long long UINT64
unsigned int UINT32
#define AE_AML_ALIGNMENT
Definition: acexcep.h:206
#define AE_BAD_PARAMETER
Definition: acexcep.h:151
#define AE_AML_OPERAND_VALUE
Definition: acexcep.h:183
#define AE_NO_MEMORY
Definition: acexcep.h:112
#define AE_OK
Definition: acexcep.h:97
#define ACPI_GET16(ptr)
Definition: acmacros.h:58
#define ACPI_SET8(ptr, val)
Definition: acmacros.h:61
#define ACPI_GET32(ptr)
Definition: acmacros.h:59
#define ACPI_FORMAT_UINT64(i)
Definition: acmacros.h:71
#define ACPI_DIV_8(a)
Definition: acmacros.h:214
#define ACPI_SET64(ptr, val)
Definition: acmacros.h:64
#define ACPI_GET8(ptr)
Definition: acmacros.h:57
#define ACPI_ROUND_UP(value, boundary)
Definition: acmacros.h:242
#define ACPI_SET32(ptr, val)
Definition: acmacros.h:63
#define ACPI_SET16(ptr, val)
Definition: acmacros.h:62
#define ACPI_GET64(ptr)
Definition: acmacros.h:60
#define ACPI_DEBUG_PRINT(pl)
Definition: acoutput.h:475
#define ACPI_MODULE_NAME(Name)
Definition: acoutput.h:216
#define return_ACPI_STATUS(s)
Definition: acoutput.h:496
#define ACPI_FUNCTION_TRACE(a)
Definition: acoutput.h:480
#define ACPI_ERROR(plist)
Definition: acoutput.h:240
#define AE_INFO
Definition: acoutput.h:230
#define ACPI_DB_INFO
Definition: acoutput.h:153
ACPI_STATUS AcpiOsWritePciConfiguration(ACPI_PCI_ID *PciId, UINT32 Reg, UINT64 Value, UINT32 Width)
Definition: osl.c:822
ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID *PciId, UINT32 Reg, UINT64 *Value, UINT32 Width)
Definition: osl.c:793
void * AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS Where, ACPI_SIZE Length)
Definition: osl.c:108
#define ACPI_READ
Definition: actypes.h:751
#define ACPI_FREE(a)
Definition: actypes.h:386
UINT32 ACPI_STATUS
Definition: actypes.h:460
#define ACPI_CAST_PTR(t, p)
Definition: actypes.h:544
#define ACPI_WRITE
Definition: actypes.h:752
#define ACPI_ALLOCATE_ZEROED(a)
Definition: actypes.h:385
#define ACPI_PTR_TO_PHYSADDR(i)
Definition: actypes.h:559
ACPI_STATUS AcpiUtShortDivide(UINT64 InDividend, UINT32 Divisor, UINT64 *OutQuotient, UINT32 *OutRemainder)
Definition: utmath.c:337
_In_ CDROM_SCAN_FOR_SPECIAL_INFO _In_ PCDROM_SCAN_FOR_SPECIAL_HANDLER Function
Definition: cdrom.h:1156
#define NULL
Definition: types.h:112
#define ACPI_DEFAULT_PAGE_SIZE
Definition: acconfig.h:132
static PVOID Mapping[EMS_PHYSICAL_PAGES]
Definition: emsdrv.c:41
ACPI_STATUS AcpiExSystemMemorySpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 BitWidth, UINT64 *Value, void *HandlerContext, void *RegionContext)
Definition: exregion.c:72
ACPI_STATUS AcpiExPciBarSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 BitWidth, UINT64 *Value, void *HandlerContext, void *RegionContext)
Definition: exregion.c:542
ACPI_STATUS AcpiExCmosSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 BitWidth, UINT64 *Value, void *HandlerContext, void *RegionContext)
Definition: exregion.c:505
ACPI_STATUS AcpiExDataTableSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 BitWidth, UINT64 *Value, void *HandlerContext, void *RegionContext)
Definition: exregion.c:579
ACPI_STATUS AcpiExPciConfigSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 BitWidth, UINT64 *Value, void *HandlerContext, void *RegionContext)
Definition: exregion.c:424
ACPI_STATUS AcpiExSystemIoSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 BitWidth, UINT64 *Value, void *HandlerContext, void *RegionContext)
Definition: exregion.c:359
Status
Definition: gdiplustypes.h:25
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
ACPI_STATUS AcpiHwWritePort(ACPI_IO_ADDRESS Address, UINT32 Value, UINT32 Width)
Definition: hwvalid.c:312
ACPI_STATUS AcpiHwReadPort(ACPI_IO_ADDRESS Address, UINT32 *Value, UINT32 Width)
Definition: hwvalid.c:237
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
static WCHAR Address[46]
Definition: ping.c:68
ACPI_SIZE Length
Definition: actypes.h:1362
struct acpi_mem_mapping * NextMm
Definition: actypes.h:1363
UINT8 * LogicalAddress
Definition: actypes.h:1361
ACPI_PHYSICAL_ADDRESS PhysicalAddress
Definition: actypes.h:1360
ACPI_PHYSICAL_ADDRESS Address
Definition: actypes.h:1370
ACPI_MEM_MAPPING * CurMm
Definition: actypes.h:1371
ACPI_MEM_MAPPING * FirstMm
Definition: actypes.h:1372
UINT16 Device
Definition: actypes.h:1353
UINT16 Function
Definition: actypes.h:1354
UINT16 Segment
Definition: actypes.h:1351
UINT16 Bus
Definition: actypes.h:1352
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS PhysicalAddress
Definition: iotypes.h:1098
_In_ LARGE_INTEGER _Out_opt_ PLARGE_INTEGER Remainder
Definition: rtlfuncs.h:3045