exregion.c revision 1.1.1.17 1 /******************************************************************************
2 *
3 * Module Name: exregion - ACPI default OpRegion (address space) handlers
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2023, 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 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
87 UINT32 Remainder;
88 #endif
89
90
91 ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler);
92
93
94 /* Validate and translate the bit width */
95
96 switch (BitWidth)
97 {
98 case 8:
99
100 Length = 1;
101 break;
102
103 case 16:
104
105 Length = 2;
106 break;
107
108 case 32:
109
110 Length = 4;
111 break;
112
113 case 64:
114
115 Length = 8;
116 break;
117
118 default:
119
120 ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %u",
121 BitWidth));
122 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
123 }
124
125 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
126 /*
127 * Hardware does not support non-aligned data transfers, we must verify
128 * the request.
129 */
130 (void) AcpiUtShortDivide ((UINT64) Address, Length, NULL, &Remainder);
131 if (Remainder != 0)
132 {
133 return_ACPI_STATUS (AE_AML_ALIGNMENT);
134 }
135 #endif
136
137 /*
138 * Does the request fit into the cached memory mapping?
139 * Is 1) Address below the current mapping? OR
140 * 2) Address beyond the current mapping?
141 */
142 if (!Mm || (Address < Mm->PhysicalAddress) ||
143 ((UINT64) Address + Length > (UINT64) Mm->PhysicalAddress + Mm->Length))
144 {
145 /*
146 * The request cannot be resolved by the current memory mapping.
147 *
148 * Look for an existing saved mapping covering the address range
149 * at hand. If found, save it as the current one and carry out
150 * the access.
151 */
152 for (Mm = MemInfo->FirstMm; Mm; Mm = Mm->NextMm)
153 {
154 if (Mm == MemInfo->CurMm)
155 {
156 continue;
157 }
158
159 if (Address < Mm->PhysicalAddress)
160 {
161 continue;
162 }
163
164 if ((UINT64) Address + Length > (UINT64) Mm->PhysicalAddress + Mm->Length)
165 {
166 continue;
167 }
168
169 MemInfo->CurMm = Mm;
170 goto access;
171 }
172
173 /* Create a new mappings list entry */
174
175 Mm = ACPI_ALLOCATE_ZEROED(sizeof(*Mm));
176 if (!Mm)
177 {
178 ACPI_ERROR((AE_INFO,
179 "Unable to save memory mapping at 0x%8.8X%8.8X, size %u",
180 ACPI_FORMAT_UINT64(Address), Length));
181 return_ACPI_STATUS(AE_NO_MEMORY);
182 }
183
184 /*
185 * October 2009: Attempt to map from the requested address to the
186 * end of the region. However, we will never map more than one
187 * page, nor will we cross a page boundary.
188 */
189 MapLength = (ACPI_SIZE)
190 ((MemInfo->Address + MemInfo->Length) - Address);
191
192 if (MapLength > ACPI_DEFAULT_PAGE_SIZE)
193 {
194 MapLength = ACPI_DEFAULT_PAGE_SIZE;
195 }
196
197 /* Create a new mapping starting at the address given */
198
199 LogicalAddrPtr = AcpiOsMapMemory(Address, MapLength);
200 if (!LogicalAddrPtr)
201 {
202 ACPI_ERROR ((AE_INFO,
203 "Could not map memory at 0x%8.8X%8.8X, size %u",
204 ACPI_FORMAT_UINT64 (Address), (UINT32) MapLength));
205 ACPI_FREE(Mm);
206 return_ACPI_STATUS (AE_NO_MEMORY);
207 }
208
209 /* Save the physical address and mapping size */
210
211 Mm->LogicalAddress = LogicalAddrPtr;
212 Mm->PhysicalAddress = Address;
213 Mm->Length = MapLength;
214
215 /*
216 * Add the new entry to the mappigs list and save it as the
217 * current mapping.
218 */
219 Mm->NextMm = MemInfo->FirstMm;
220 MemInfo->FirstMm = Mm;
221 MemInfo->CurMm = Mm;
222 }
223
224 access:
225 /*
226 * Generate a logical pointer corresponding to the address we want to
227 * access
228 */
229 LogicalAddrPtr = Mm->LogicalAddress +
230 ((UINT64) Address - (UINT64) Mm->PhysicalAddress);
231
232 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
233 "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
234 BitWidth, Function, ACPI_FORMAT_UINT64 (Address)));
235
236 /*
237 * Perform the memory read or write
238 *
239 * Note: For machines that do not support non-aligned transfers, the target
240 * address was checked for alignment above. We do not attempt to break the
241 * transfer up into smaller (byte-size) chunks because the AML specifically
242 * asked for a transfer width that the hardware may require.
243 */
244 switch (Function)
245 {
246 case ACPI_READ:
247
248 *Value = 0;
249 switch (BitWidth)
250 {
251 case 8:
252
253 *Value = (UINT64) ACPI_GET8 (LogicalAddrPtr);
254 break;
255
256 case 16:
257
258 *Value = (UINT64) ACPI_GET16 (LogicalAddrPtr);
259 break;
260
261 case 32:
262
263 *Value = (UINT64) ACPI_GET32 (LogicalAddrPtr);
264 break;
265
266 case 64:
267
268 *Value = (UINT64) ACPI_GET64 (LogicalAddrPtr);
269 break;
270
271 default:
272
273 /* BitWidth was already validated */
274
275 break;
276 }
277 break;
278
279 case ACPI_WRITE:
280
281 switch (BitWidth)
282 {
283 case 8:
284
285 ACPI_SET8 (LogicalAddrPtr, *Value);
286 break;
287
288 case 16:
289
290 ACPI_SET16 (LogicalAddrPtr, *Value);
291 break;
292
293 case 32:
294
295 ACPI_SET32 (LogicalAddrPtr, *Value);
296 break;
297
298 case 64:
299
300 ACPI_SET64 (LogicalAddrPtr, *Value);
301 break;
302
303 default:
304
305 /* BitWidth was already validated */
306
307 break;
308 }
309 break;
310
311 default:
312
313 Status = AE_BAD_PARAMETER;
314 break;
315 }
316
317 return_ACPI_STATUS (Status);
318 }
319
320
321 /*******************************************************************************
322 *
323 * FUNCTION: AcpiExSystemIoSpaceHandler
324 *
325 * PARAMETERS: Function - Read or Write operation
326 * Address - Where in the space to read or write
327 * BitWidth - Field width in bits (8, 16, or 32)
328 * Value - Pointer to in or out value
329 * HandlerContext - Pointer to Handler's context
330 * RegionContext - Pointer to context specific to the
331 * accessed region
332 *
333 * RETURN: Status
334 *
335 * DESCRIPTION: Handler for the System IO address space (Op Region)
336 *
337 ******************************************************************************/
338
339 ACPI_STATUS
340 AcpiExSystemIoSpaceHandler (
341 UINT32 Function,
342 ACPI_PHYSICAL_ADDRESS Address,
343 UINT32 BitWidth,
344 UINT64 *Value,
345 void *HandlerContext,
346 void *RegionContext)
347 {
348 ACPI_STATUS Status = AE_OK;
349 UINT32 Value32;
350
351
352 ACPI_FUNCTION_TRACE (ExSystemIoSpaceHandler);
353
354
355 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
356 "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
357 BitWidth, Function, ACPI_FORMAT_UINT64 (Address)));
358
359 /* Decode the function parameter */
360
361 switch (Function)
362 {
363 case ACPI_READ:
364
365 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) Address,
366 &Value32, BitWidth);
367 *Value = Value32;
368 break;
369
370 case ACPI_WRITE:
371
372 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) Address,
373 (UINT32) *Value, BitWidth);
374 break;
375
376 default:
377
378 Status = AE_BAD_PARAMETER;
379 break;
380 }
381
382 return_ACPI_STATUS (Status);
383 }
384
385
386 /*******************************************************************************
387 *
388 * FUNCTION: AcpiExPciConfigSpaceHandler
389 *
390 * PARAMETERS: Function - Read or Write operation
391 * Address - Where in the space to read or write
392 * BitWidth - Field width in bits (8, 16, or 32)
393 * Value - Pointer to in or out value
394 * HandlerContext - Pointer to Handler's context
395 * RegionContext - Pointer to context specific to the
396 * accessed region
397 *
398 * RETURN: Status
399 *
400 * DESCRIPTION: Handler for the PCI Config address space (Op Region)
401 *
402 ******************************************************************************/
403
404 ACPI_STATUS
405 AcpiExPciConfigSpaceHandler (
406 UINT32 Function,
407 ACPI_PHYSICAL_ADDRESS Address,
408 UINT32 BitWidth,
409 UINT64 *Value,
410 void *HandlerContext,
411 void *RegionContext)
412 {
413 ACPI_STATUS Status = AE_OK;
414 ACPI_PCI_ID *PciId;
415 UINT16 PciRegister;
416
417
418 ACPI_FUNCTION_TRACE (ExPciConfigSpaceHandler);
419
420
421 /*
422 * The arguments to AcpiOs(Read|Write)PciConfiguration are:
423 *
424 * PciSegment is the PCI bus segment range 0-31
425 * PciBus is the PCI bus number range 0-255
426 * PciDevice is the PCI device number range 0-31
427 * PciFunction is the PCI device function number
428 * PciRegister is the Config space register range 0-255 bytes
429 *
430 * Value - input value for write, output address for read
431 *
432 */
433 PciId = (ACPI_PCI_ID *) RegionContext;
434 PciRegister = (UINT16) (UINT32) Address;
435
436 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
437 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) "
438 "Dev(%04x) Func(%04x) Reg(%04x)\n",
439 Function, BitWidth, PciId->Segment, PciId->Bus, PciId->Device,
440 PciId->Function, PciRegister));
441
442 switch (Function)
443 {
444 case ACPI_READ:
445
446 *Value = 0;
447 Status = AcpiOsReadPciConfiguration (
448 PciId, PciRegister, Value, BitWidth);
449 break;
450
451 case ACPI_WRITE:
452
453 Status = AcpiOsWritePciConfiguration (
454 PciId, PciRegister, *Value, BitWidth);
455 break;
456
457 default:
458
459 Status = AE_BAD_PARAMETER;
460 break;
461 }
462
463 return_ACPI_STATUS (Status);
464 }
465
466
467 /*******************************************************************************
468 *
469 * FUNCTION: AcpiExCmosSpaceHandler
470 *
471 * PARAMETERS: Function - Read or Write operation
472 * Address - Where in the space to read or write
473 * BitWidth - Field width in bits (8, 16, or 32)
474 * Value - Pointer to in or out value
475 * HandlerContext - Pointer to Handler's context
476 * RegionContext - Pointer to context specific to the
477 * accessed region
478 *
479 * RETURN: Status
480 *
481 * DESCRIPTION: Handler for the CMOS address space (Op Region)
482 *
483 ******************************************************************************/
484
485 ACPI_STATUS
486 AcpiExCmosSpaceHandler (
487 UINT32 Function,
488 ACPI_PHYSICAL_ADDRESS Address,
489 UINT32 BitWidth,
490 UINT64 *Value,
491 void *HandlerContext,
492 void *RegionContext)
493 {
494 ACPI_STATUS Status = AE_OK;
495
496
497 ACPI_FUNCTION_TRACE (ExCmosSpaceHandler);
498
499
500 return_ACPI_STATUS (Status);
501 }
502
503
504 /*******************************************************************************
505 *
506 * FUNCTION: AcpiExPciBarSpaceHandler
507 *
508 * PARAMETERS: Function - Read or Write operation
509 * Address - Where in the space to read or write
510 * BitWidth - Field width in bits (8, 16, or 32)
511 * Value - Pointer to in or out value
512 * HandlerContext - Pointer to Handler's context
513 * RegionContext - Pointer to context specific to the
514 * accessed region
515 *
516 * RETURN: Status
517 *
518 * DESCRIPTION: Handler for the PCI BarTarget address space (Op Region)
519 *
520 ******************************************************************************/
521
522 ACPI_STATUS
523 AcpiExPciBarSpaceHandler (
524 UINT32 Function,
525 ACPI_PHYSICAL_ADDRESS Address,
526 UINT32 BitWidth,
527 UINT64 *Value,
528 void *HandlerContext,
529 void *RegionContext)
530 {
531 ACPI_STATUS Status = AE_OK;
532
533
534 ACPI_FUNCTION_TRACE (ExPciBarSpaceHandler);
535
536
537 return_ACPI_STATUS (Status);
538 }
539
540
541 /*******************************************************************************
542 *
543 * FUNCTION: AcpiExDataTableSpaceHandler
544 *
545 * PARAMETERS: Function - Read or Write operation
546 * Address - Where in the space to read or write
547 * BitWidth - Field width in bits (8, 16, or 32)
548 * Value - Pointer to in or out value
549 * HandlerContext - Pointer to Handler's context
550 * RegionContext - Pointer to context specific to the
551 * accessed region
552 *
553 * RETURN: Status
554 *
555 * DESCRIPTION: Handler for the Data Table address space (Op Region)
556 *
557 ******************************************************************************/
558
559 ACPI_STATUS
560 AcpiExDataTableSpaceHandler (
561 UINT32 Function,
562 ACPI_PHYSICAL_ADDRESS Address,
563 UINT32 BitWidth,
564 UINT64 *Value,
565 void *HandlerContext,
566 void *RegionContext)
567 {
568 ACPI_DATA_TABLE_MAPPING *Mapping;
569 char *Pointer;
570
571
572 ACPI_FUNCTION_TRACE (ExDataTableSpaceHandler);
573
574
575 Mapping = (ACPI_DATA_TABLE_MAPPING *) RegionContext;
576 Pointer = ACPI_CAST_PTR (char, Mapping->Pointer) +
577 (Address - ACPI_PTR_TO_PHYSADDR (Mapping->Pointer));
578
579 /*
580 * Perform the memory read or write. The BitWidth was already
581 * validated.
582 */
583 switch (Function)
584 {
585 case ACPI_READ:
586
587 memcpy (ACPI_CAST_PTR (char, Value), Pointer, ACPI_DIV_8 (BitWidth));
588 break;
589
590 case ACPI_WRITE:
591
592 memcpy (Pointer, ACPI_CAST_PTR (char, Value), ACPI_DIV_8 (BitWidth));
593 break;
594
595 default:
596
597 return_ACPI_STATUS (AE_BAD_PARAMETER);
598 }
599
600 return_ACPI_STATUS (AE_OK);
601 }
602