• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Module Name: exregion - ACPI default op_region (address space) handlers
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2014, 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 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.
42  */
43 
44 #include <acpi/acpi.h>
45 #include "accommon.h"
46 #include "acinterp.h"
47 
48 #define _COMPONENT          ACPI_EXECUTER
49 ACPI_MODULE_NAME("exregion")
50 
51 /*******************************************************************************
52  *
53  * FUNCTION:    acpi_ex_system_memory_space_handler
54  *
55  * PARAMETERS:  function            - Read or Write operation
56  *              address             - Where in the space to read or write
57  *              bit_width           - Field width in bits (8, 16, or 32)
58  *              value               - Pointer to in or out value
59  *              handler_context     - Pointer to Handler's context
60  *              region_context      - Pointer to context specific to the
61  *                                    accessed region
62  *
63  * RETURN:      Status
64  *
65  * DESCRIPTION: Handler for the System Memory address space (Op Region)
66  *
67  ******************************************************************************/
68 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)69 acpi_ex_system_memory_space_handler(u32 function,
70 				    acpi_physical_address address,
71 				    u32 bit_width,
72 				    u64 *value,
73 				    void *handler_context, void *region_context)
74 {
75 	acpi_status status = AE_OK;
76 	void *logical_addr_ptr = NULL;
77 	struct acpi_mem_space_context *mem_info = region_context;
78 	u32 length;
79 	acpi_size map_length;
80 	acpi_size page_boundary_map_length;
81 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
82 	u32 remainder;
83 #endif
84 
85 	ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
86 
87 	/* Validate and translate the bit width */
88 
89 	switch (bit_width) {
90 	case 8:
91 
92 		length = 1;
93 		break;
94 
95 	case 16:
96 
97 		length = 2;
98 		break;
99 
100 	case 32:
101 
102 		length = 4;
103 		break;
104 
105 	case 64:
106 
107 		length = 8;
108 		break;
109 
110 	default:
111 
112 		ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %u",
113 			    bit_width));
114 		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
115 	}
116 
117 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
118 	/*
119 	 * Hardware does not support non-aligned data transfers, we must verify
120 	 * the request.
121 	 */
122 	(void)acpi_ut_short_divide((u64) address, length, NULL, &remainder);
123 	if (remainder != 0) {
124 		return_ACPI_STATUS(AE_AML_ALIGNMENT);
125 	}
126 #endif
127 
128 	/*
129 	 * Does the request fit into the cached memory mapping?
130 	 * Is 1) Address below the current mapping? OR
131 	 *    2) Address beyond the current mapping?
132 	 */
133 	if ((address < mem_info->mapped_physical_address) ||
134 	    (((u64) address + length) > ((u64)
135 					 mem_info->mapped_physical_address +
136 					 mem_info->mapped_length))) {
137 		/*
138 		 * The request cannot be resolved by the current memory mapping;
139 		 * Delete the existing mapping and create a new one.
140 		 */
141 		if (mem_info->mapped_length) {
142 
143 			/* Valid mapping, delete it */
144 
145 			acpi_os_unmap_memory(mem_info->mapped_logical_address,
146 					     mem_info->mapped_length);
147 		}
148 
149 		/*
150 		 * October 2009: Attempt to map from the requested address to the
151 		 * end of the region. However, we will never map more than one
152 		 * page, nor will we cross a page boundary.
153 		 */
154 		map_length = (acpi_size)
155 		    ((mem_info->address + mem_info->length) - address);
156 
157 		/*
158 		 * If mapping the entire remaining portion of the region will cross
159 		 * a page boundary, just map up to the page boundary, do not cross.
160 		 * On some systems, crossing a page boundary while mapping regions
161 		 * can cause warnings if the pages have different attributes
162 		 * due to resource management.
163 		 *
164 		 * This has the added benefit of constraining a single mapping to
165 		 * one page, which is similar to the original code that used a 4k
166 		 * maximum window.
167 		 */
168 		page_boundary_map_length =
169 		    ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address;
170 		if (page_boundary_map_length == 0) {
171 			page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE;
172 		}
173 
174 		if (map_length > page_boundary_map_length) {
175 			map_length = page_boundary_map_length;
176 		}
177 
178 		/* Create a new mapping starting at the address given */
179 
180 		mem_info->mapped_logical_address = acpi_os_map_memory((acpi_physical_address) address, map_length);
181 		if (!mem_info->mapped_logical_address) {
182 			ACPI_ERROR((AE_INFO,
183 				    "Could not map memory at 0x%8.8X%8.8X, size %u",
184 				    ACPI_FORMAT_UINT64(address),
185 				    (u32) map_length));
186 			mem_info->mapped_length = 0;
187 			return_ACPI_STATUS(AE_NO_MEMORY);
188 		}
189 
190 		/* Save the physical address and mapping size */
191 
192 		mem_info->mapped_physical_address = address;
193 		mem_info->mapped_length = map_length;
194 	}
195 
196 	/*
197 	 * Generate a logical pointer corresponding to the address we want to
198 	 * access
199 	 */
200 	logical_addr_ptr = mem_info->mapped_logical_address +
201 	    ((u64) address - (u64) mem_info->mapped_physical_address);
202 
203 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
204 			  "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
205 			  bit_width, function, ACPI_FORMAT_UINT64(address)));
206 
207 	/*
208 	 * Perform the memory read or write
209 	 *
210 	 * Note: For machines that do not support non-aligned transfers, the target
211 	 * address was checked for alignment above. We do not attempt to break the
212 	 * transfer up into smaller (byte-size) chunks because the AML specifically
213 	 * asked for a transfer width that the hardware may require.
214 	 */
215 	switch (function) {
216 	case ACPI_READ:
217 
218 		*value = 0;
219 		switch (bit_width) {
220 		case 8:
221 
222 			*value = (u64)ACPI_GET8(logical_addr_ptr);
223 			break;
224 
225 		case 16:
226 
227 			*value = (u64)ACPI_GET16(logical_addr_ptr);
228 			break;
229 
230 		case 32:
231 
232 			*value = (u64)ACPI_GET32(logical_addr_ptr);
233 			break;
234 
235 		case 64:
236 
237 			*value = (u64)ACPI_GET64(logical_addr_ptr);
238 			break;
239 
240 		default:
241 
242 			/* bit_width was already validated */
243 
244 			break;
245 		}
246 		break;
247 
248 	case ACPI_WRITE:
249 
250 		switch (bit_width) {
251 		case 8:
252 
253 			ACPI_SET8(logical_addr_ptr, *value);
254 			break;
255 
256 		case 16:
257 
258 			ACPI_SET16(logical_addr_ptr, *value);
259 			break;
260 
261 		case 32:
262 
263 			ACPI_SET32(logical_addr_ptr, *value);
264 			break;
265 
266 		case 64:
267 
268 			ACPI_SET64(logical_addr_ptr, *value);
269 			break;
270 
271 		default:
272 
273 			/* bit_width was already validated */
274 
275 			break;
276 		}
277 		break;
278 
279 	default:
280 
281 		status = AE_BAD_PARAMETER;
282 		break;
283 	}
284 
285 	return_ACPI_STATUS(status);
286 }
287 
288 /*******************************************************************************
289  *
290  * FUNCTION:    acpi_ex_system_io_space_handler
291  *
292  * PARAMETERS:  function            - Read or Write operation
293  *              address             - Where in the space to read or write
294  *              bit_width           - Field width in bits (8, 16, or 32)
295  *              value               - Pointer to in or out value
296  *              handler_context     - Pointer to Handler's context
297  *              region_context      - Pointer to context specific to the
298  *                                    accessed region
299  *
300  * RETURN:      Status
301  *
302  * DESCRIPTION: Handler for the System IO address space (Op Region)
303  *
304  ******************************************************************************/
305 
306 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)307 acpi_ex_system_io_space_handler(u32 function,
308 				acpi_physical_address address,
309 				u32 bit_width,
310 				u64 *value,
311 				void *handler_context, void *region_context)
312 {
313 	acpi_status status = AE_OK;
314 	u32 value32;
315 
316 	ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
317 
318 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
319 			  "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
320 			  bit_width, function, ACPI_FORMAT_UINT64(address)));
321 
322 	/* Decode the function parameter */
323 
324 	switch (function) {
325 	case ACPI_READ:
326 
327 		status = acpi_hw_read_port((acpi_io_address) address,
328 					   &value32, bit_width);
329 		*value = value32;
330 		break;
331 
332 	case ACPI_WRITE:
333 
334 		status = acpi_hw_write_port((acpi_io_address) address,
335 					    (u32) * value, bit_width);
336 		break;
337 
338 	default:
339 
340 		status = AE_BAD_PARAMETER;
341 		break;
342 	}
343 
344 	return_ACPI_STATUS(status);
345 }
346 
347 /*******************************************************************************
348  *
349  * FUNCTION:    acpi_ex_pci_config_space_handler
350  *
351  * PARAMETERS:  function            - Read or Write operation
352  *              address             - Where in the space to read or write
353  *              bit_width           - Field width in bits (8, 16, or 32)
354  *              value               - Pointer to in or out value
355  *              handler_context     - Pointer to Handler's context
356  *              region_context      - Pointer to context specific to the
357  *                                    accessed region
358  *
359  * RETURN:      Status
360  *
361  * DESCRIPTION: Handler for the PCI Config address space (Op Region)
362  *
363  ******************************************************************************/
364 
365 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)366 acpi_ex_pci_config_space_handler(u32 function,
367 				 acpi_physical_address address,
368 				 u32 bit_width,
369 				 u64 *value,
370 				 void *handler_context, void *region_context)
371 {
372 	acpi_status status = AE_OK;
373 	struct acpi_pci_id *pci_id;
374 	u16 pci_register;
375 
376 	ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
377 
378 	/*
379 	 *  The arguments to acpi_os(Read|Write)pci_configuration are:
380 	 *
381 	 *  pci_segment is the PCI bus segment range 0-31
382 	 *  pci_bus     is the PCI bus number range 0-255
383 	 *  pci_device  is the PCI device number range 0-31
384 	 *  pci_function is the PCI device function number
385 	 *  pci_register is the Config space register range 0-255 bytes
386 	 *
387 	 *  value - input value for write, output address for read
388 	 *
389 	 */
390 	pci_id = (struct acpi_pci_id *)region_context;
391 	pci_register = (u16) (u32) address;
392 
393 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
394 			  "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
395 			  function, bit_width, pci_id->segment, pci_id->bus,
396 			  pci_id->device, pci_id->function, pci_register));
397 
398 	switch (function) {
399 	case ACPI_READ:
400 
401 		*value = 0;
402 		status = acpi_os_read_pci_configuration(pci_id, pci_register,
403 							value, bit_width);
404 		break;
405 
406 	case ACPI_WRITE:
407 
408 		status = acpi_os_write_pci_configuration(pci_id, pci_register,
409 							 *value, bit_width);
410 		break;
411 
412 	default:
413 
414 		status = AE_BAD_PARAMETER;
415 		break;
416 	}
417 
418 	return_ACPI_STATUS(status);
419 }
420 
421 /*******************************************************************************
422  *
423  * FUNCTION:    acpi_ex_cmos_space_handler
424  *
425  * PARAMETERS:  function            - Read or Write operation
426  *              address             - Where in the space to read or write
427  *              bit_width           - Field width in bits (8, 16, or 32)
428  *              value               - Pointer to in or out value
429  *              handler_context     - Pointer to Handler's context
430  *              region_context      - Pointer to context specific to the
431  *                                    accessed region
432  *
433  * RETURN:      Status
434  *
435  * DESCRIPTION: Handler for the CMOS address space (Op Region)
436  *
437  ******************************************************************************/
438 
439 acpi_status
acpi_ex_cmos_space_handler(u32 function,acpi_physical_address address,u32 bit_width,u64 * value,void * handler_context,void * region_context)440 acpi_ex_cmos_space_handler(u32 function,
441 			   acpi_physical_address address,
442 			   u32 bit_width,
443 			   u64 *value,
444 			   void *handler_context, void *region_context)
445 {
446 	acpi_status status = AE_OK;
447 
448 	ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
449 
450 	return_ACPI_STATUS(status);
451 }
452 
453 /*******************************************************************************
454  *
455  * FUNCTION:    acpi_ex_pci_bar_space_handler
456  *
457  * PARAMETERS:  function            - Read or Write operation
458  *              address             - Where in the space to read or write
459  *              bit_width           - Field width in bits (8, 16, or 32)
460  *              value               - Pointer to in or out value
461  *              handler_context     - Pointer to Handler's context
462  *              region_context      - Pointer to context specific to the
463  *                                    accessed region
464  *
465  * RETURN:      Status
466  *
467  * DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
468  *
469  ******************************************************************************/
470 
471 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)472 acpi_ex_pci_bar_space_handler(u32 function,
473 			      acpi_physical_address address,
474 			      u32 bit_width,
475 			      u64 *value,
476 			      void *handler_context, void *region_context)
477 {
478 	acpi_status status = AE_OK;
479 
480 	ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
481 
482 	return_ACPI_STATUS(status);
483 }
484 
485 /*******************************************************************************
486  *
487  * FUNCTION:    acpi_ex_data_table_space_handler
488  *
489  * PARAMETERS:  function            - Read or Write operation
490  *              address             - Where in the space to read or write
491  *              bit_width           - Field width in bits (8, 16, or 32)
492  *              value               - Pointer to in or out value
493  *              handler_context     - Pointer to Handler's context
494  *              region_context      - Pointer to context specific to the
495  *                                    accessed region
496  *
497  * RETURN:      Status
498  *
499  * DESCRIPTION: Handler for the Data Table address space (Op Region)
500  *
501  ******************************************************************************/
502 
503 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)504 acpi_ex_data_table_space_handler(u32 function,
505 				 acpi_physical_address address,
506 				 u32 bit_width,
507 				 u64 *value,
508 				 void *handler_context, void *region_context)
509 {
510 	ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
511 
512 	/*
513 	 * Perform the memory read or write. The bit_width was already
514 	 * validated.
515 	 */
516 	switch (function) {
517 	case ACPI_READ:
518 
519 		ACPI_MEMCPY(ACPI_CAST_PTR(char, value),
520 			    ACPI_PHYSADDR_TO_PTR(address),
521 			    ACPI_DIV_8(bit_width));
522 		break;
523 
524 	case ACPI_WRITE:
525 
526 		ACPI_MEMCPY(ACPI_PHYSADDR_TO_PTR(address),
527 			    ACPI_CAST_PTR(char, value), ACPI_DIV_8(bit_width));
528 		break;
529 
530 	default:
531 
532 		return_ACPI_STATUS(AE_BAD_PARAMETER);
533 	}
534 
535 	return_ACPI_STATUS(AE_OK);
536 }
537