1 /******************************************************************************
3 * Module Name: exregion - ACPI default OpRegion (address space) handlers
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2012, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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 MERCHANTIBILITY 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.
45 #define __EXREGION_C__
52 #define _COMPONENT ACPI_EXECUTER
53 ACPI_MODULE_NAME ("exregion")
56 /*******************************************************************************
58 * FUNCTION: AcpiExSystemMemorySpaceHandler
60 * PARAMETERS: Function - Read or Write operation
61 * Address - Where in the space to read or write
62 * BitWidth - Field width in bits (8, 16, or 32)
63 * Value - Pointer to in or out value
64 * HandlerContext - Pointer to Handler's context
65 * RegionContext - Pointer to context specific to the
70 * DESCRIPTION: Handler for the System Memory address space (Op Region)
72 ******************************************************************************/
75 AcpiExSystemMemorySpaceHandler (
77 ACPI_PHYSICAL_ADDRESS Address,
83 ACPI_STATUS Status = AE_OK;
84 void *LogicalAddrPtr = NULL;
85 ACPI_MEM_SPACE_CONTEXT *MemInfo = RegionContext;
88 ACPI_SIZE PageBoundaryMapLength;
89 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
94 ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler);
97 /* Validate and translate the bit width */
118 ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %u",
120 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
123 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
125 * Hardware does not support non-aligned data transfers, we must verify
128 (void) AcpiUtShortDivide ((UINT64) Address, Length, NULL, &Remainder);
131 return_ACPI_STATUS (AE_AML_ALIGNMENT);
136 * Does the request fit into the cached memory mapping?
137 * Is 1) Address below the current mapping? OR
138 * 2) Address beyond the current mapping?
140 if ((Address < MemInfo->MappedPhysicalAddress) ||
141 (((UINT64) Address + Length) >
143 MemInfo->MappedPhysicalAddress + MemInfo->MappedLength)))
146 * The request cannot be resolved by the current memory mapping;
147 * Delete the existing mapping and create a new one.
149 if (MemInfo->MappedLength)
151 /* Valid mapping, delete it */
153 AcpiOsUnmapMemory (MemInfo->MappedLogicalAddress,
154 MemInfo->MappedLength);
158 * October 2009: Attempt to map from the requested address to the
159 * end of the region. However, we will never map more than one
160 * page, nor will we cross a page boundary.
162 MapLength = (ACPI_SIZE)
163 ((MemInfo->Address + MemInfo->Length) - Address);
166 * If mapping the entire remaining portion of the region will cross
167 * a page boundary, just map up to the page boundary, do not cross.
168 * On some systems, crossing a page boundary while mapping regions
169 * can cause warnings if the pages have different attributes
170 * due to resource management.
172 * This has the added benefit of constraining a single mapping to
173 * one page, which is similar to the original code that used a 4k
176 PageBoundaryMapLength =
177 ACPI_ROUND_UP (Address, ACPI_DEFAULT_PAGE_SIZE) - Address;
178 if (PageBoundaryMapLength == 0)
180 PageBoundaryMapLength = ACPI_DEFAULT_PAGE_SIZE;
183 if (MapLength > PageBoundaryMapLength)
185 MapLength = PageBoundaryMapLength;
188 /* Create a new mapping starting at the address given */
190 MemInfo->MappedLogicalAddress = AcpiOsMapMemory (
191 (ACPI_PHYSICAL_ADDRESS) Address, MapLength);
192 if (!MemInfo->MappedLogicalAddress)
194 ACPI_ERROR ((AE_INFO,
195 "Could not map memory at 0x%8.8X%8.8X, size %u",
196 ACPI_FORMAT_NATIVE_UINT (Address), (UINT32) MapLength));
197 MemInfo->MappedLength = 0;
198 return_ACPI_STATUS (AE_NO_MEMORY);
201 /* Save the physical address and mapping size */
203 MemInfo->MappedPhysicalAddress = Address;
204 MemInfo->MappedLength = MapLength;
208 * Generate a logical pointer corresponding to the address we want to
211 LogicalAddrPtr = MemInfo->MappedLogicalAddress +
212 ((UINT64) Address - (UINT64) MemInfo->MappedPhysicalAddress);
214 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
215 "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
216 BitWidth, Function, ACPI_FORMAT_NATIVE_UINT (Address)));
219 * Perform the memory read or write
221 * Note: For machines that do not support non-aligned transfers, the target
222 * address was checked for alignment above. We do not attempt to break the
223 * transfer up into smaller (byte-size) chunks because the AML specifically
224 * asked for a transfer width that the hardware may require.
234 *Value = (UINT64) ACPI_GET8 (LogicalAddrPtr);
238 *Value = (UINT64) ACPI_GET16 (LogicalAddrPtr);
242 *Value = (UINT64) ACPI_GET32 (LogicalAddrPtr);
246 *Value = (UINT64) ACPI_GET64 (LogicalAddrPtr);
250 /* BitWidth was already validated */
260 ACPI_SET8 (LogicalAddrPtr) = (UINT8) *Value;
264 ACPI_SET16 (LogicalAddrPtr) = (UINT16) *Value;
268 ACPI_SET32 ( LogicalAddrPtr) = (UINT32) *Value;
272 ACPI_SET64 (LogicalAddrPtr) = (UINT64) *Value;
276 /* BitWidth was already validated */
282 Status = AE_BAD_PARAMETER;
286 return_ACPI_STATUS (Status);
290 /*******************************************************************************
292 * FUNCTION: AcpiExSystemIoSpaceHandler
294 * PARAMETERS: Function - Read or Write operation
295 * Address - Where in the space to read or write
296 * BitWidth - Field width in bits (8, 16, or 32)
297 * Value - Pointer to in or out value
298 * HandlerContext - Pointer to Handler's context
299 * RegionContext - Pointer to context specific to the
304 * DESCRIPTION: Handler for the System IO address space (Op Region)
306 ******************************************************************************/
309 AcpiExSystemIoSpaceHandler (
311 ACPI_PHYSICAL_ADDRESS Address,
314 void *HandlerContext,
317 ACPI_STATUS Status = AE_OK;
321 ACPI_FUNCTION_TRACE (ExSystemIoSpaceHandler);
324 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
325 "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
326 BitWidth, Function, ACPI_FORMAT_NATIVE_UINT (Address)));
328 /* Decode the function parameter */
334 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) Address,
341 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) Address,
342 (UINT32) *Value, BitWidth);
346 Status = AE_BAD_PARAMETER;
350 return_ACPI_STATUS (Status);
354 /*******************************************************************************
356 * FUNCTION: AcpiExPciConfigSpaceHandler
358 * PARAMETERS: Function - Read or Write operation
359 * Address - Where in the space to read or write
360 * BitWidth - Field width in bits (8, 16, or 32)
361 * Value - Pointer to in or out value
362 * HandlerContext - Pointer to Handler's context
363 * RegionContext - Pointer to context specific to the
368 * DESCRIPTION: Handler for the PCI Config address space (Op Region)
370 ******************************************************************************/
373 AcpiExPciConfigSpaceHandler (
375 ACPI_PHYSICAL_ADDRESS Address,
378 void *HandlerContext,
381 ACPI_STATUS Status = AE_OK;
386 ACPI_FUNCTION_TRACE (ExPciConfigSpaceHandler);
390 * The arguments to AcpiOs(Read|Write)PciConfiguration are:
392 * PciSegment is the PCI bus segment range 0-31
393 * PciBus is the PCI bus number range 0-255
394 * PciDevice is the PCI device number range 0-31
395 * PciFunction is the PCI device function number
396 * PciRegister is the Config space register range 0-255 bytes
398 * Value - input value for write, output address for read
401 PciId = (ACPI_PCI_ID *) RegionContext;
402 PciRegister = (UINT16) (UINT32) Address;
404 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
405 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
406 Function, BitWidth, PciId->Segment, PciId->Bus, PciId->Device,
407 PciId->Function, PciRegister));
414 Status = AcpiOsReadPciConfiguration (PciId, PciRegister,
420 Status = AcpiOsWritePciConfiguration (PciId, PciRegister,
426 Status = AE_BAD_PARAMETER;
430 return_ACPI_STATUS (Status);
434 /*******************************************************************************
436 * FUNCTION: AcpiExCmosSpaceHandler
438 * PARAMETERS: Function - Read or Write operation
439 * Address - Where in the space to read or write
440 * BitWidth - Field width in bits (8, 16, or 32)
441 * Value - Pointer to in or out value
442 * HandlerContext - Pointer to Handler's context
443 * RegionContext - Pointer to context specific to the
448 * DESCRIPTION: Handler for the CMOS address space (Op Region)
450 ******************************************************************************/
453 AcpiExCmosSpaceHandler (
455 ACPI_PHYSICAL_ADDRESS Address,
458 void *HandlerContext,
461 ACPI_STATUS Status = AE_OK;
464 ACPI_FUNCTION_TRACE (ExCmosSpaceHandler);
467 return_ACPI_STATUS (Status);
471 /*******************************************************************************
473 * FUNCTION: AcpiExPciBarSpaceHandler
475 * PARAMETERS: Function - Read or Write operation
476 * Address - Where in the space to read or write
477 * BitWidth - Field width in bits (8, 16, or 32)
478 * Value - Pointer to in or out value
479 * HandlerContext - Pointer to Handler's context
480 * RegionContext - Pointer to context specific to the
485 * DESCRIPTION: Handler for the PCI BarTarget address space (Op Region)
487 ******************************************************************************/
490 AcpiExPciBarSpaceHandler (
492 ACPI_PHYSICAL_ADDRESS Address,
495 void *HandlerContext,
498 ACPI_STATUS Status = AE_OK;
501 ACPI_FUNCTION_TRACE (ExPciBarSpaceHandler);
504 return_ACPI_STATUS (Status);
508 /*******************************************************************************
510 * FUNCTION: AcpiExDataTableSpaceHandler
512 * PARAMETERS: Function - Read or Write operation
513 * Address - Where in the space to read or write
514 * BitWidth - Field width in bits (8, 16, or 32)
515 * Value - Pointer to in or out value
516 * HandlerContext - Pointer to Handler's context
517 * RegionContext - Pointer to context specific to the
522 * DESCRIPTION: Handler for the Data Table address space (Op Region)
524 ******************************************************************************/
527 AcpiExDataTableSpaceHandler (
529 ACPI_PHYSICAL_ADDRESS Address,
532 void *HandlerContext,
535 ACPI_FUNCTION_TRACE (ExDataTableSpaceHandler);
539 * Perform the memory read or write. The BitWidth was already
546 ACPI_MEMCPY (ACPI_CAST_PTR (char, Value), ACPI_PHYSADDR_TO_PTR (Address),
547 ACPI_DIV_8 (BitWidth));
552 ACPI_MEMCPY (ACPI_PHYSADDR_TO_PTR (Address), ACPI_CAST_PTR (char, Value),
553 ACPI_DIV_8 (BitWidth));
558 return_ACPI_STATUS (AE_BAD_PARAMETER);
561 return_ACPI_STATUS (AE_OK);