xref: /openbmc/linux/drivers/acpi/acpica/exregion.c (revision 612c2932)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: exregion - ACPI default op_region (address space) handlers
595b482a8SLen Brown  *
6*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
795b482a8SLen Brown  *
895857638SErik Schmauss  *****************************************************************************/
995b482a8SLen Brown 
1095b482a8SLen Brown #include <acpi/acpi.h>
11e2f7a777SLen Brown #include "accommon.h"
12e2f7a777SLen Brown #include "acinterp.h"
1395b482a8SLen Brown 
1495b482a8SLen Brown #define _COMPONENT          ACPI_EXECUTER
1595b482a8SLen Brown ACPI_MODULE_NAME("exregion")
1695b482a8SLen Brown 
1795b482a8SLen Brown /*******************************************************************************
1895b482a8SLen Brown  *
1995b482a8SLen Brown  * FUNCTION:    acpi_ex_system_memory_space_handler
2095b482a8SLen Brown  *
21ba494beeSBob Moore  * PARAMETERS:  function            - Read or Write operation
22ba494beeSBob Moore  *              address             - Where in the space to read or write
2395b482a8SLen Brown  *              bit_width           - Field width in bits (8, 16, or 32)
24ba494beeSBob Moore  *              value               - Pointer to in or out value
2595b482a8SLen Brown  *              handler_context     - Pointer to Handler's context
2695b482a8SLen Brown  *              region_context      - Pointer to context specific to the
2795b482a8SLen Brown  *                                    accessed region
2895b482a8SLen Brown  *
2995b482a8SLen Brown  * RETURN:      Status
3095b482a8SLen Brown  *
3195b482a8SLen Brown  * DESCRIPTION: Handler for the System Memory address space (Op Region)
3295b482a8SLen Brown  *
3395b482a8SLen Brown  ******************************************************************************/
3495b482a8SLen Brown acpi_status
acpi_ex_system_memory_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)3595b482a8SLen Brown acpi_ex_system_memory_space_handler(u32 function,
3695b482a8SLen Brown 				    acpi_physical_address address,
3795b482a8SLen Brown 				    u32 bit_width,
385df7e6cbSBob Moore 				    u64 *value,
3995b482a8SLen Brown 				    void *handler_context, void *region_context)
4095b482a8SLen Brown {
4195b482a8SLen Brown 	acpi_status status = AE_OK;
4295b482a8SLen Brown 	void *logical_addr_ptr = NULL;
4395b482a8SLen Brown 	struct acpi_mem_space_context *mem_info = region_context;
44b8fcd0e5SRafael J. Wysocki 	struct acpi_mem_mapping *mm = mem_info->cur_mm;
4595b482a8SLen Brown 	u32 length;
46d410ee51SBob Moore 	acpi_size map_length;
47d410ee51SBob Moore 	acpi_size page_boundary_map_length;
4895b482a8SLen Brown #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
4995b482a8SLen Brown 	u32 remainder;
5095b482a8SLen Brown #endif
5195b482a8SLen Brown 
5295b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
5395b482a8SLen Brown 
5495b482a8SLen Brown 	/* Validate and translate the bit width */
5595b482a8SLen Brown 
5695b482a8SLen Brown 	switch (bit_width) {
5795b482a8SLen Brown 	case 8:
581d1ea1b7SChao Guan 
5995b482a8SLen Brown 		length = 1;
6095b482a8SLen Brown 		break;
6195b482a8SLen Brown 
6295b482a8SLen Brown 	case 16:
631d1ea1b7SChao Guan 
6495b482a8SLen Brown 		length = 2;
6595b482a8SLen Brown 		break;
6695b482a8SLen Brown 
6795b482a8SLen Brown 	case 32:
681d1ea1b7SChao Guan 
6995b482a8SLen Brown 		length = 4;
7095b482a8SLen Brown 		break;
7195b482a8SLen Brown 
7295b482a8SLen Brown 	case 64:
731d1ea1b7SChao Guan 
7495b482a8SLen Brown 		length = 8;
7595b482a8SLen Brown 		break;
7695b482a8SLen Brown 
7795b482a8SLen Brown 	default:
781d1ea1b7SChao Guan 
79f6a22b0bSBob Moore 		ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u",
8095b482a8SLen Brown 			    bit_width));
8195b482a8SLen Brown 		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
8295b482a8SLen Brown 	}
8395b482a8SLen Brown 
8495b482a8SLen Brown #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
8595b482a8SLen Brown 	/*
8695b482a8SLen Brown 	 * Hardware does not support non-aligned data transfers, we must verify
8795b482a8SLen Brown 	 * the request.
8895b482a8SLen Brown 	 */
895df7e6cbSBob Moore 	(void)acpi_ut_short_divide((u64) address, length, NULL, &remainder);
9095b482a8SLen Brown 	if (remainder != 0) {
9195b482a8SLen Brown 		return_ACPI_STATUS(AE_AML_ALIGNMENT);
9295b482a8SLen Brown 	}
9395b482a8SLen Brown #endif
9495b482a8SLen Brown 
9595b482a8SLen Brown 	/*
9695b482a8SLen Brown 	 * Does the request fit into the cached memory mapping?
9795b482a8SLen Brown 	 * Is 1) Address below the current mapping? OR
9895b482a8SLen Brown 	 *    2) Address beyond the current mapping?
9995b482a8SLen Brown 	 */
100b8fcd0e5SRafael J. Wysocki 	if (!mm || (address < mm->physical_address) ||
101b8fcd0e5SRafael J. Wysocki 	    ((u64) address + length > (u64) mm->physical_address + mm->length)) {
10295b482a8SLen Brown 		/*
103b8fcd0e5SRafael J. Wysocki 		 * The request cannot be resolved by the current memory mapping.
104b8fcd0e5SRafael J. Wysocki 		 *
105b8fcd0e5SRafael J. Wysocki 		 * Look for an existing saved mapping covering the address range
106b8fcd0e5SRafael J. Wysocki 		 * at hand.  If found, save it as the current one and carry out
107b8fcd0e5SRafael J. Wysocki 		 * the access.
10895b482a8SLen Brown 		 */
109b8fcd0e5SRafael J. Wysocki 		for (mm = mem_info->first_mm; mm; mm = mm->next_mm) {
110b8fcd0e5SRafael J. Wysocki 			if (mm == mem_info->cur_mm)
111b8fcd0e5SRafael J. Wysocki 				continue;
11295b482a8SLen Brown 
113b8fcd0e5SRafael J. Wysocki 			if (address < mm->physical_address)
114b8fcd0e5SRafael J. Wysocki 				continue;
11595b482a8SLen Brown 
116b8fcd0e5SRafael J. Wysocki 			if ((u64) address + length >
117b8fcd0e5SRafael J. Wysocki 					(u64) mm->physical_address + mm->length)
118b8fcd0e5SRafael J. Wysocki 				continue;
119b8fcd0e5SRafael J. Wysocki 
120b8fcd0e5SRafael J. Wysocki 			mem_info->cur_mm = mm;
121b8fcd0e5SRafael J. Wysocki 			goto access;
122b8fcd0e5SRafael J. Wysocki 		}
123b8fcd0e5SRafael J. Wysocki 
124b8fcd0e5SRafael J. Wysocki 		/* Create a new mappings list entry */
125b8fcd0e5SRafael J. Wysocki 		mm = ACPI_ALLOCATE_ZEROED(sizeof(*mm));
126b8fcd0e5SRafael J. Wysocki 		if (!mm) {
127b8fcd0e5SRafael J. Wysocki 			ACPI_ERROR((AE_INFO,
128b8fcd0e5SRafael J. Wysocki 				    "Unable to save memory mapping at 0x%8.8X%8.8X, size %u",
129b8fcd0e5SRafael J. Wysocki 				    ACPI_FORMAT_UINT64(address), length));
130b8fcd0e5SRafael J. Wysocki 			return_ACPI_STATUS(AE_NO_MEMORY);
13195b482a8SLen Brown 		}
13295b482a8SLen Brown 
13395b482a8SLen Brown 		/*
13475c8044fSLv Zheng 		 * October 2009: Attempt to map from the requested address to the
13575c8044fSLv Zheng 		 * end of the region. However, we will never map more than one
13675c8044fSLv Zheng 		 * page, nor will we cross a page boundary.
13795b482a8SLen Brown 		 */
138d410ee51SBob Moore 		map_length = (acpi_size)
13995b482a8SLen Brown 		    ((mem_info->address + mem_info->length) - address);
14095b482a8SLen Brown 
141d410ee51SBob Moore 		/*
142d410ee51SBob Moore 		 * If mapping the entire remaining portion of the region will cross
143d410ee51SBob Moore 		 * a page boundary, just map up to the page boundary, do not cross.
144d410ee51SBob Moore 		 * On some systems, crossing a page boundary while mapping regions
145d410ee51SBob Moore 		 * can cause warnings if the pages have different attributes
14675c8044fSLv Zheng 		 * due to resource management.
14775c8044fSLv Zheng 		 *
14875c8044fSLv Zheng 		 * This has the added benefit of constraining a single mapping to
14975c8044fSLv Zheng 		 * one page, which is similar to the original code that used a 4k
15075c8044fSLv Zheng 		 * maximum window.
151d410ee51SBob Moore 		 */
152938ed102SBob Moore 		page_boundary_map_length = (acpi_size)
153938ed102SBob Moore 		    (ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address);
154739dcbb9SLv Zheng 		if (page_boundary_map_length == 0) {
155d410ee51SBob Moore 			page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE;
156d410ee51SBob Moore 		}
157d410ee51SBob Moore 
158d410ee51SBob Moore 		if (map_length > page_boundary_map_length) {
159d410ee51SBob Moore 			map_length = page_boundary_map_length;
16095b482a8SLen Brown 		}
16195b482a8SLen Brown 
16295b482a8SLen Brown 		/* Create a new mapping starting at the address given */
16395b482a8SLen Brown 
164b8fcd0e5SRafael J. Wysocki 		logical_addr_ptr = acpi_os_map_memory(address, map_length);
165b8fcd0e5SRafael J. Wysocki 		if (!logical_addr_ptr) {
16695b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
167f6a22b0bSBob Moore 				    "Could not map memory at 0x%8.8X%8.8X, size %u",
1681d0a0b2fSLv Zheng 				    ACPI_FORMAT_UINT64(address),
169d410ee51SBob Moore 				    (u32)map_length));
170b8fcd0e5SRafael J. Wysocki 			ACPI_FREE(mm);
17195b482a8SLen Brown 			return_ACPI_STATUS(AE_NO_MEMORY);
17295b482a8SLen Brown 		}
17395b482a8SLen Brown 
17495b482a8SLen Brown 		/* Save the physical address and mapping size */
17595b482a8SLen Brown 
176b8fcd0e5SRafael J. Wysocki 		mm->logical_address = logical_addr_ptr;
177b8fcd0e5SRafael J. Wysocki 		mm->physical_address = address;
178b8fcd0e5SRafael J. Wysocki 		mm->length = map_length;
179b8fcd0e5SRafael J. Wysocki 
180b8fcd0e5SRafael J. Wysocki 		/*
181b8fcd0e5SRafael J. Wysocki 		 * Add the new entry to the mappigs list and save it as the
182b8fcd0e5SRafael J. Wysocki 		 * current mapping.
183b8fcd0e5SRafael J. Wysocki 		 */
184b8fcd0e5SRafael J. Wysocki 		mm->next_mm = mem_info->first_mm;
185b8fcd0e5SRafael J. Wysocki 		mem_info->first_mm = mm;
186b8fcd0e5SRafael J. Wysocki 
187b8fcd0e5SRafael J. Wysocki 		mem_info->cur_mm = mm;
18895b482a8SLen Brown 	}
18995b482a8SLen Brown 
190b8fcd0e5SRafael J. Wysocki access:
19195b482a8SLen Brown 	/*
19295b482a8SLen Brown 	 * Generate a logical pointer corresponding to the address we want to
19395b482a8SLen Brown 	 * access
19495b482a8SLen Brown 	 */
195b8fcd0e5SRafael J. Wysocki 	logical_addr_ptr = mm->logical_address +
196b8fcd0e5SRafael J. Wysocki 		((u64) address - (u64) mm->physical_address);
19795b482a8SLen Brown 
19895b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
199b27d6597SBob Moore 			  "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
2001d0a0b2fSLv Zheng 			  bit_width, function, ACPI_FORMAT_UINT64(address)));
20195b482a8SLen Brown 
20295b482a8SLen Brown 	/*
20395b482a8SLen Brown 	 * Perform the memory read or write
20495b482a8SLen Brown 	 *
20595b482a8SLen Brown 	 * Note: For machines that do not support non-aligned transfers, the target
20695b482a8SLen Brown 	 * address was checked for alignment above. We do not attempt to break the
20795b482a8SLen Brown 	 * transfer up into smaller (byte-size) chunks because the AML specifically
20895b482a8SLen Brown 	 * asked for a transfer width that the hardware may require.
20995b482a8SLen Brown 	 */
21095b482a8SLen Brown 	switch (function) {
21195b482a8SLen Brown 	case ACPI_READ:
21295b482a8SLen Brown 
21395b482a8SLen Brown 		*value = 0;
21495b482a8SLen Brown 		switch (bit_width) {
21595b482a8SLen Brown 		case 8:
2161d1ea1b7SChao Guan 
2175df7e6cbSBob Moore 			*value = (u64)ACPI_GET8(logical_addr_ptr);
21895b482a8SLen Brown 			break;
21995b482a8SLen Brown 
22095b482a8SLen Brown 		case 16:
2211d1ea1b7SChao Guan 
2225df7e6cbSBob Moore 			*value = (u64)ACPI_GET16(logical_addr_ptr);
22395b482a8SLen Brown 			break;
22495b482a8SLen Brown 
22595b482a8SLen Brown 		case 32:
2261d1ea1b7SChao Guan 
2275df7e6cbSBob Moore 			*value = (u64)ACPI_GET32(logical_addr_ptr);
22895b482a8SLen Brown 			break;
22995b482a8SLen Brown 
23095b482a8SLen Brown 		case 64:
2311d1ea1b7SChao Guan 
2325df7e6cbSBob Moore 			*value = (u64)ACPI_GET64(logical_addr_ptr);
23395b482a8SLen Brown 			break;
23495b482a8SLen Brown 
23595b482a8SLen Brown 		default:
2361d1ea1b7SChao Guan 
23795b482a8SLen Brown 			/* bit_width was already validated */
2381d1ea1b7SChao Guan 
23995b482a8SLen Brown 			break;
24095b482a8SLen Brown 		}
24195b482a8SLen Brown 		break;
24295b482a8SLen Brown 
24395b482a8SLen Brown 	case ACPI_WRITE:
24495b482a8SLen Brown 
24595b482a8SLen Brown 		switch (bit_width) {
24695b482a8SLen Brown 		case 8:
2471d1ea1b7SChao Guan 
24857bf6aefSLv Zheng 			ACPI_SET8(logical_addr_ptr, *value);
24995b482a8SLen Brown 			break;
25095b482a8SLen Brown 
25195b482a8SLen Brown 		case 16:
2521d1ea1b7SChao Guan 
25357bf6aefSLv Zheng 			ACPI_SET16(logical_addr_ptr, *value);
25495b482a8SLen Brown 			break;
25595b482a8SLen Brown 
25695b482a8SLen Brown 		case 32:
2571d1ea1b7SChao Guan 
25857bf6aefSLv Zheng 			ACPI_SET32(logical_addr_ptr, *value);
25995b482a8SLen Brown 			break;
26095b482a8SLen Brown 
26195b482a8SLen Brown 		case 64:
2621d1ea1b7SChao Guan 
26357bf6aefSLv Zheng 			ACPI_SET64(logical_addr_ptr, *value);
26495b482a8SLen Brown 			break;
26595b482a8SLen Brown 
26695b482a8SLen Brown 		default:
2671d1ea1b7SChao Guan 
26895b482a8SLen Brown 			/* bit_width was already validated */
2691d1ea1b7SChao Guan 
27095b482a8SLen Brown 			break;
27195b482a8SLen Brown 		}
27295b482a8SLen Brown 		break;
27395b482a8SLen Brown 
27495b482a8SLen Brown 	default:
2751d1ea1b7SChao Guan 
27695b482a8SLen Brown 		status = AE_BAD_PARAMETER;
27795b482a8SLen Brown 		break;
27895b482a8SLen Brown 	}
27995b482a8SLen Brown 
28095b482a8SLen Brown 	return_ACPI_STATUS(status);
28195b482a8SLen Brown }
28295b482a8SLen Brown 
28395b482a8SLen Brown /*******************************************************************************
28495b482a8SLen Brown  *
28595b482a8SLen Brown  * FUNCTION:    acpi_ex_system_io_space_handler
28695b482a8SLen Brown  *
287ba494beeSBob Moore  * PARAMETERS:  function            - Read or Write operation
288ba494beeSBob Moore  *              address             - Where in the space to read or write
28995b482a8SLen Brown  *              bit_width           - Field width in bits (8, 16, or 32)
290ba494beeSBob Moore  *              value               - Pointer to in or out value
29195b482a8SLen Brown  *              handler_context     - Pointer to Handler's context
29295b482a8SLen Brown  *              region_context      - Pointer to context specific to the
29395b482a8SLen Brown  *                                    accessed region
29495b482a8SLen Brown  *
29595b482a8SLen Brown  * RETURN:      Status
29695b482a8SLen Brown  *
29795b482a8SLen Brown  * DESCRIPTION: Handler for the System IO address space (Op Region)
29895b482a8SLen Brown  *
29995b482a8SLen Brown  ******************************************************************************/
30095b482a8SLen Brown 
30195b482a8SLen Brown acpi_status
acpi_ex_system_io_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)30295b482a8SLen Brown acpi_ex_system_io_space_handler(u32 function,
30395b482a8SLen Brown 				acpi_physical_address address,
30495b482a8SLen Brown 				u32 bit_width,
3055df7e6cbSBob Moore 				u64 *value,
30695b482a8SLen Brown 				void *handler_context, void *region_context)
30795b482a8SLen Brown {
30895b482a8SLen Brown 	acpi_status status = AE_OK;
30995b482a8SLen Brown 	u32 value32;
31095b482a8SLen Brown 
31195b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
31295b482a8SLen Brown 
31395b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
314b27d6597SBob Moore 			  "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
3151d0a0b2fSLv Zheng 			  bit_width, function, ACPI_FORMAT_UINT64(address)));
31695b482a8SLen Brown 
31795b482a8SLen Brown 	/* Decode the function parameter */
31895b482a8SLen Brown 
31995b482a8SLen Brown 	switch (function) {
32095b482a8SLen Brown 	case ACPI_READ:
32195b482a8SLen Brown 
3227f071903SBob Moore 		status = acpi_hw_read_port((acpi_io_address)address,
32395b482a8SLen Brown 					   &value32, bit_width);
32495b482a8SLen Brown 		*value = value32;
32595b482a8SLen Brown 		break;
32695b482a8SLen Brown 
32795b482a8SLen Brown 	case ACPI_WRITE:
32895b482a8SLen Brown 
3297f071903SBob Moore 		status = acpi_hw_write_port((acpi_io_address)address,
33095b482a8SLen Brown 					    (u32)*value, bit_width);
33195b482a8SLen Brown 		break;
33295b482a8SLen Brown 
33395b482a8SLen Brown 	default:
3341d1ea1b7SChao Guan 
33595b482a8SLen Brown 		status = AE_BAD_PARAMETER;
33695b482a8SLen Brown 		break;
33795b482a8SLen Brown 	}
33895b482a8SLen Brown 
33995b482a8SLen Brown 	return_ACPI_STATUS(status);
34095b482a8SLen Brown }
34195b482a8SLen Brown 
342bd23fac3SSinan Kaya #ifdef ACPI_PCI_CONFIGURED
34395b482a8SLen Brown /*******************************************************************************
34495b482a8SLen Brown  *
34595b482a8SLen Brown  * FUNCTION:    acpi_ex_pci_config_space_handler
34695b482a8SLen Brown  *
347ba494beeSBob Moore  * PARAMETERS:  function            - Read or Write operation
348ba494beeSBob Moore  *              address             - Where in the space to read or write
34995b482a8SLen Brown  *              bit_width           - Field width in bits (8, 16, or 32)
350ba494beeSBob Moore  *              value               - Pointer to in or out value
35195b482a8SLen Brown  *              handler_context     - Pointer to Handler's context
35295b482a8SLen Brown  *              region_context      - Pointer to context specific to the
35395b482a8SLen Brown  *                                    accessed region
35495b482a8SLen Brown  *
35595b482a8SLen Brown  * RETURN:      Status
35695b482a8SLen Brown  *
35795b482a8SLen Brown  * DESCRIPTION: Handler for the PCI Config address space (Op Region)
35895b482a8SLen Brown  *
35995b482a8SLen Brown  ******************************************************************************/
36095b482a8SLen Brown 
36195b482a8SLen Brown acpi_status
acpi_ex_pci_config_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)36295b482a8SLen Brown acpi_ex_pci_config_space_handler(u32 function,
36395b482a8SLen Brown 				 acpi_physical_address address,
36495b482a8SLen Brown 				 u32 bit_width,
3655df7e6cbSBob Moore 				 u64 *value,
36695b482a8SLen Brown 				 void *handler_context, void *region_context)
36795b482a8SLen Brown {
36895b482a8SLen Brown 	acpi_status status = AE_OK;
36995b482a8SLen Brown 	struct acpi_pci_id *pci_id;
37095b482a8SLen Brown 	u16 pci_register;
37195b482a8SLen Brown 
37295b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
37395b482a8SLen Brown 
37495b482a8SLen Brown 	/*
37595b482a8SLen Brown 	 *  The arguments to acpi_os(Read|Write)pci_configuration are:
37695b482a8SLen Brown 	 *
37795b482a8SLen Brown 	 *  pci_segment is the PCI bus segment range 0-31
37895b482a8SLen Brown 	 *  pci_bus     is the PCI bus number range 0-255
37995b482a8SLen Brown 	 *  pci_device  is the PCI device number range 0-31
38095b482a8SLen Brown 	 *  pci_function is the PCI device function number
38195b482a8SLen Brown 	 *  pci_register is the Config space register range 0-255 bytes
38295b482a8SLen Brown 	 *
383ba494beeSBob Moore 	 *  value - input value for write, output address for read
38495b482a8SLen Brown 	 *
38595b482a8SLen Brown 	 */
38695b482a8SLen Brown 	pci_id = (struct acpi_pci_id *)region_context;
38795b482a8SLen Brown 	pci_register = (u16) (u32) address;
38895b482a8SLen Brown 
38995b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
3901fad8738SBob Moore 			  "Pci-Config %u (%u) Seg(%04x) Bus(%04x) "
3911fad8738SBob Moore 			  "Dev(%04x) Func(%04x) Reg(%04x)\n",
39295b482a8SLen Brown 			  function, bit_width, pci_id->segment, pci_id->bus,
39395b482a8SLen Brown 			  pci_id->device, pci_id->function, pci_register));
39495b482a8SLen Brown 
39595b482a8SLen Brown 	switch (function) {
39695b482a8SLen Brown 	case ACPI_READ:
39795b482a8SLen Brown 
398bb42cc22SLv Zheng 		*value = 0;
3991fad8738SBob Moore 		status =
4001fad8738SBob Moore 		    acpi_os_read_pci_configuration(pci_id, pci_register, value,
4011fad8738SBob Moore 						   bit_width);
40295b482a8SLen Brown 		break;
40395b482a8SLen Brown 
40495b482a8SLen Brown 	case ACPI_WRITE:
40595b482a8SLen Brown 
4061fad8738SBob Moore 		status =
4071fad8738SBob Moore 		    acpi_os_write_pci_configuration(pci_id, pci_register,
40895b482a8SLen Brown 						    *value, bit_width);
40995b482a8SLen Brown 		break;
41095b482a8SLen Brown 
41195b482a8SLen Brown 	default:
41295b482a8SLen Brown 
41395b482a8SLen Brown 		status = AE_BAD_PARAMETER;
41495b482a8SLen Brown 		break;
41595b482a8SLen Brown 	}
41695b482a8SLen Brown 
41795b482a8SLen Brown 	return_ACPI_STATUS(status);
41895b482a8SLen Brown }
419bd23fac3SSinan Kaya #endif
42095b482a8SLen Brown 
42195b482a8SLen Brown /*******************************************************************************
42295b482a8SLen Brown  *
42395b482a8SLen Brown  * FUNCTION:    acpi_ex_cmos_space_handler
42495b482a8SLen Brown  *
425ba494beeSBob Moore  * PARAMETERS:  function            - Read or Write operation
426ba494beeSBob Moore  *              address             - Where in the space to read or write
42795b482a8SLen Brown  *              bit_width           - Field width in bits (8, 16, or 32)
428ba494beeSBob Moore  *              value               - Pointer to in or out value
42995b482a8SLen Brown  *              handler_context     - Pointer to Handler's context
43095b482a8SLen Brown  *              region_context      - Pointer to context specific to the
43195b482a8SLen Brown  *                                    accessed region
43295b482a8SLen Brown  *
43395b482a8SLen Brown  * RETURN:      Status
43495b482a8SLen Brown  *
43595b482a8SLen Brown  * DESCRIPTION: Handler for the CMOS address space (Op Region)
43695b482a8SLen Brown  *
43795b482a8SLen Brown  ******************************************************************************/
43895b482a8SLen Brown 
43995b482a8SLen Brown acpi_status
acpi_ex_cmos_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)44095b482a8SLen Brown acpi_ex_cmos_space_handler(u32 function,
44195b482a8SLen Brown 			   acpi_physical_address address,
44295b482a8SLen Brown 			   u32 bit_width,
4435df7e6cbSBob Moore 			   u64 *value,
44495b482a8SLen Brown 			   void *handler_context, void *region_context)
44595b482a8SLen Brown {
44695b482a8SLen Brown 	acpi_status status = AE_OK;
44795b482a8SLen Brown 
44895b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
44995b482a8SLen Brown 
45095b482a8SLen Brown 	return_ACPI_STATUS(status);
45195b482a8SLen Brown }
45295b482a8SLen Brown 
453bd23fac3SSinan Kaya #ifdef ACPI_PCI_CONFIGURED
45495b482a8SLen Brown /*******************************************************************************
45595b482a8SLen Brown  *
45695b482a8SLen Brown  * FUNCTION:    acpi_ex_pci_bar_space_handler
45795b482a8SLen Brown  *
458ba494beeSBob Moore  * PARAMETERS:  function            - Read or Write operation
459ba494beeSBob Moore  *              address             - Where in the space to read or write
46095b482a8SLen Brown  *              bit_width           - Field width in bits (8, 16, or 32)
461ba494beeSBob Moore  *              value               - Pointer to in or out value
46295b482a8SLen Brown  *              handler_context     - Pointer to Handler's context
46395b482a8SLen Brown  *              region_context      - Pointer to context specific to the
46495b482a8SLen Brown  *                                    accessed region
46595b482a8SLen Brown  *
46695b482a8SLen Brown  * RETURN:      Status
46795b482a8SLen Brown  *
46895b482a8SLen Brown  * DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
46995b482a8SLen Brown  *
47095b482a8SLen Brown  ******************************************************************************/
47195b482a8SLen Brown 
47295b482a8SLen Brown acpi_status
acpi_ex_pci_bar_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)47395b482a8SLen Brown acpi_ex_pci_bar_space_handler(u32 function,
47495b482a8SLen Brown 			      acpi_physical_address address,
47595b482a8SLen Brown 			      u32 bit_width,
4765df7e6cbSBob Moore 			      u64 *value,
47795b482a8SLen Brown 			      void *handler_context, void *region_context)
47895b482a8SLen Brown {
47995b482a8SLen Brown 	acpi_status status = AE_OK;
48095b482a8SLen Brown 
48195b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
48295b482a8SLen Brown 
48395b482a8SLen Brown 	return_ACPI_STATUS(status);
48495b482a8SLen Brown }
485bd23fac3SSinan Kaya #endif
48695b482a8SLen Brown 
48795b482a8SLen Brown /*******************************************************************************
48895b482a8SLen Brown  *
48995b482a8SLen Brown  * FUNCTION:    acpi_ex_data_table_space_handler
49095b482a8SLen Brown  *
491ba494beeSBob Moore  * PARAMETERS:  function            - Read or Write operation
492ba494beeSBob Moore  *              address             - Where in the space to read or write
49395b482a8SLen Brown  *              bit_width           - Field width in bits (8, 16, or 32)
494ba494beeSBob Moore  *              value               - Pointer to in or out value
49595b482a8SLen Brown  *              handler_context     - Pointer to Handler's context
49695b482a8SLen Brown  *              region_context      - Pointer to context specific to the
49795b482a8SLen Brown  *                                    accessed region
49895b482a8SLen Brown  *
49995b482a8SLen Brown  * RETURN:      Status
50095b482a8SLen Brown  *
50195b482a8SLen Brown  * DESCRIPTION: Handler for the Data Table address space (Op Region)
50295b482a8SLen Brown  *
50395b482a8SLen Brown  ******************************************************************************/
50495b482a8SLen Brown 
50595b482a8SLen Brown acpi_status
acpi_ex_data_table_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)50695b482a8SLen Brown acpi_ex_data_table_space_handler(u32 function,
50795b482a8SLen Brown 				 acpi_physical_address address,
50895b482a8SLen Brown 				 u32 bit_width,
5095df7e6cbSBob Moore 				 u64 *value,
51095b482a8SLen Brown 				 void *handler_context, void *region_context)
51195b482a8SLen Brown {
5129737ff46SPedro Falcato 	struct acpi_data_table_mapping *mapping;
513ca25f92bSJessica Clarke 	char *pointer;
514ca25f92bSJessica Clarke 
51595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
51695b482a8SLen Brown 
5179737ff46SPedro Falcato 	mapping = (struct acpi_data_table_mapping *) region_context;
518ca25f92bSJessica Clarke 	pointer = ACPI_CAST_PTR(char, mapping->pointer) +
519ca25f92bSJessica Clarke 	    (address - ACPI_PTR_TO_PHYSADDR(mapping->pointer));
520ca25f92bSJessica Clarke 
521c1637e9cSBob Moore 	/*
522c1637e9cSBob Moore 	 * Perform the memory read or write. The bit_width was already
523c1637e9cSBob Moore 	 * validated.
524c1637e9cSBob Moore 	 */
52595b482a8SLen Brown 	switch (function) {
52695b482a8SLen Brown 	case ACPI_READ:
52795b482a8SLen Brown 
528ca25f92bSJessica Clarke 		memcpy(ACPI_CAST_PTR(char, value), pointer,
529ca25f92bSJessica Clarke 		       ACPI_DIV_8(bit_width));
53095b482a8SLen Brown 		break;
53195b482a8SLen Brown 
53295b482a8SLen Brown 	case ACPI_WRITE:
533c1637e9cSBob Moore 
534ca25f92bSJessica Clarke 		memcpy(pointer, ACPI_CAST_PTR(char, value),
535ca25f92bSJessica Clarke 		       ACPI_DIV_8(bit_width));
536c1637e9cSBob Moore 		break;
537c1637e9cSBob Moore 
53895b482a8SLen Brown 	default:
53995b482a8SLen Brown 
540c1637e9cSBob Moore 		return_ACPI_STATUS(AE_BAD_PARAMETER);
54195b482a8SLen Brown 	}
54295b482a8SLen Brown 
54395b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
54495b482a8SLen Brown }
545