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