b7e50e35ecb54c2673875c26203b2feb92bf3389
[reactos.git] / drivers / bus / acpi / acpica / executer / exregion.c
1 /******************************************************************************
2 *
3 * Module Name: exregion - ACPI default OpRegion (address space) handlers
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2021, 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
71 ACPI_STATUS
72 AcpiExSystemMemorySpaceHandler (
73 UINT32 Function,
74 ACPI_PHYSICAL_ADDRESS Address,
75 UINT32 BitWidth,
76 UINT64 *Value,
77 void *HandlerContext,
78 void *RegionContext)
79 {
80 ACPI_STATUS Status = AE_OK;
81 void *LogicalAddrPtr = NULL;
82 ACPI_MEM_SPACE_CONTEXT *MemInfo = RegionContext;
83 ACPI_MEM_MAPPING *Mm = MemInfo->CurMm;
84 UINT32 Length;
85 ACPI_SIZE MapLength;
86 ACPI_SIZE PageBoundaryMapLength;
87 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
88 UINT32 Remainder;
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));
123 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
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 */
131 (void) AcpiUtShortDivide ((UINT64) Address, Length, NULL, &Remainder);
132 if (Remainder != 0)
133 {
134 return_ACPI_STATUS (AE_AML_ALIGNMENT);
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 {
179 ACPI_ERROR((AE_INFO,
180 "Unable to save memory mapping at 0x%8.8X%8.8X, size %u",
181 ACPI_FORMAT_UINT64(Address), Length));
182 return_ACPI_STATUS(AE_NO_MEMORY);
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)
205 (ACPI_ROUND_UP (Address, ACPI_DEFAULT_PAGE_SIZE) - Address);
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 {
221 ACPI_ERROR ((AE_INFO,
222 "Could not map memory at 0x%8.8X%8.8X, size %u",
223 ACPI_FORMAT_UINT64 (Address), (UINT32) MapLength));
224 ACPI_FREE(Mm);
225 return_ACPI_STATUS (AE_NO_MEMORY);
226 }
227
228 /* Save the physical address and mapping size */
229
230 Mm->LogicalAddress = LogicalAddrPtr;
231 Mm->PhysicalAddress = Address;
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
243 access:
244 /*
245 * Generate a logical pointer corresponding to the address we want to
246 * access
247 */
248 LogicalAddrPtr = Mm->LogicalAddress +
249 ((UINT64) Address - (UINT64) Mm->PhysicalAddress);
250
251 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
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
332 Status = AE_BAD_PARAMETER;
333 break;
334 }
335
336 return_ACPI_STATUS (Status);
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
358 ACPI_STATUS
359 AcpiExSystemIoSpaceHandler (
360 UINT32 Function,
361 ACPI_PHYSICAL_ADDRESS Address,
362 UINT32 BitWidth,
363 UINT64 *Value,
364 void *HandlerContext,
365 void *RegionContext)
366 {
367 ACPI_STATUS Status = AE_OK;
368 UINT32 Value32;
369
370
371 ACPI_FUNCTION_TRACE (ExSystemIoSpaceHandler);
372
373
374 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
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
397 Status = AE_BAD_PARAMETER;
398 break;
399 }
400
401 return_ACPI_STATUS (Status);
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
423 ACPI_STATUS
424 AcpiExPciConfigSpaceHandler (
425 UINT32 Function,
426 ACPI_PHYSICAL_ADDRESS Address,
427 UINT32 BitWidth,
428 UINT64 *Value,
429 void *HandlerContext,
430 void *RegionContext)
431 {
432 ACPI_STATUS Status = AE_OK;
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
455 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
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;
466 Status = AcpiOsReadPciConfiguration (
467 PciId, PciRegister, Value, BitWidth);
468 break;
469
470 case ACPI_WRITE:
471
472 Status = AcpiOsWritePciConfiguration (
473 PciId, PciRegister, *Value, BitWidth);
474 break;
475
476 default:
477
478 Status = AE_BAD_PARAMETER;
479 break;
480 }
481
482 return_ACPI_STATUS (Status);
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
504 ACPI_STATUS
505 AcpiExCmosSpaceHandler (
506 UINT32 Function,
507 ACPI_PHYSICAL_ADDRESS Address,
508 UINT32 BitWidth,
509 UINT64 *Value,
510 void *HandlerContext,
511 void *RegionContext)
512 {
513 ACPI_STATUS Status = AE_OK;
514
515
516 ACPI_FUNCTION_TRACE (ExCmosSpaceHandler);
517
518
519 return_ACPI_STATUS (Status);
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
541 ACPI_STATUS
542 AcpiExPciBarSpaceHandler (
543 UINT32 Function,
544 ACPI_PHYSICAL_ADDRESS Address,
545 UINT32 BitWidth,
546 UINT64 *Value,
547 void *HandlerContext,
548 void *RegionContext)
549 {
550 ACPI_STATUS Status = AE_OK;
551
552
553 ACPI_FUNCTION_TRACE (ExPciBarSpaceHandler);
554
555
556 return_ACPI_STATUS (Status);
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
578 ACPI_STATUS
579 AcpiExDataTableSpaceHandler (
580 UINT32 Function,
581 ACPI_PHYSICAL_ADDRESS Address,
582 UINT32 BitWidth,
583 UINT64 *Value,
584 void *HandlerContext,
585 void *RegionContext)
586 {
587 ACPI_FUNCTION_TRACE (ExDataTableSpaceHandler);
588
589
590 /*
591 * Perform the memory read or write. The BitWidth was already
592 * validated.
593 */
594 switch (Function)
595 {
596 case ACPI_READ:
597
598 memcpy (ACPI_CAST_PTR (char, Value), ACPI_PHYSADDR_TO_PTR (Address),
599 ACPI_DIV_8 (BitWidth));
600 break;
601
602 case ACPI_WRITE:
603
604 memcpy (ACPI_PHYSADDR_TO_PTR (Address), ACPI_CAST_PTR (char, Value),
605 ACPI_DIV_8 (BitWidth));
606 break;
607
608 default:
609
610 return_ACPI_STATUS (AE_BAD_PARAMETER);
611 }
612
613 return_ACPI_STATUS (AE_OK);
614 }