1 
2 /******************************************************************************
3  *
4  * Module Name: exregion - ACPI default op_region (address space) handlers
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2004, R. Byron Moore
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 
46 #include <acpi/acpi.h>
47 #include <acpi/acinterp.h>
48 
49 
50 #define _COMPONENT          ACPI_EXECUTER
51 	 ACPI_MODULE_NAME    ("exregion")
52 
53 
54 /*******************************************************************************
55  *
56  * FUNCTION:    acpi_ex_system_memory_space_handler
57  *
58  * PARAMETERS:  Function            - Read or Write operation
59  *              Address             - Where in the space to read or write
60  *              bit_width           - Field width in bits (8, 16, or 32)
61  *              Value               - Pointer to in or out value
62  *              handler_context     - Pointer to Handler's context
63  *              region_context      - Pointer to context specific to the
64  *                                    accessed region
65  *
66  * RETURN:      Status
67  *
68  * DESCRIPTION: Handler for the System Memory address space (Op Region)
69  *
70  ******************************************************************************/
71 
72 acpi_status
acpi_ex_system_memory_space_handler(u32 function,acpi_physical_address address,u32 bit_width,acpi_integer * value,void * handler_context,void * region_context)73 acpi_ex_system_memory_space_handler (
74 	u32                             function,
75 	acpi_physical_address           address,
76 	u32                             bit_width,
77 	acpi_integer                    *value,
78 	void                            *handler_context,
79 	void                            *region_context)
80 {
81 	acpi_status                     status = AE_OK;
82 	void                            *logical_addr_ptr = NULL;
83 	struct acpi_mem_space_context   *mem_info = region_context;
84 	u32                             length;
85 	acpi_size                       window_size;
86 #ifndef ACPI_MISALIGNED_TRANSFERS
87 	u32                             remainder;
88 #endif
89 
90 	ACPI_FUNCTION_TRACE ("ex_system_memory_space_handler");
91 
92 
93 	/* Validate and translate the bit width */
94 
95 	switch (bit_width) {
96 	case 8:
97 		length = 1;
98 		break;
99 
100 	case 16:
101 		length = 2;
102 		break;
103 
104 	case 32:
105 		length = 4;
106 		break;
107 
108 	case 64:
109 		length = 8;
110 		break;
111 
112 	default:
113 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid system_memory width %d\n",
114 			bit_width));
115 		return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
116 	}
117 
118 
119 #ifndef ACPI_MISALIGNED_TRANSFERS
120 	/*
121 	 * Hardware does not support non-aligned data transfers, we must verify
122 	 * the request.
123 	 */
124 	(void) acpi_ut_short_divide ((acpi_integer *) &address, length, NULL, &remainder);
125 	if (remainder != 0) {
126 		return_ACPI_STATUS (AE_AML_ALIGNMENT);
127 	}
128 #endif
129 
130 	/*
131 	 * Does the request fit into the cached memory mapping?
132 	 * Is 1) Address below the current mapping? OR
133 	 *    2) Address beyond the current mapping?
134 	 */
135 	if ((address < mem_info->mapped_physical_address) ||
136 		(((acpi_integer) address + length) >
137 			((acpi_integer) mem_info->mapped_physical_address + mem_info->mapped_length))) {
138 		/*
139 		 * The request cannot be resolved by the current memory mapping;
140 		 * Delete the existing mapping and create a new one.
141 		 */
142 		if (mem_info->mapped_length) {
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 		 * Don't attempt to map memory beyond the end of the region, and
151 		 * constrain the maximum mapping size to something reasonable.
152 		 */
153 		window_size = (acpi_size) ((mem_info->address + mem_info->length) - address);
154 		if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) {
155 			window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE;
156 		}
157 
158 		/* Create a new mapping starting at the address given */
159 
160 		status = acpi_os_map_memory (address, window_size,
161 				  (void **) &mem_info->mapped_logical_address);
162 		if (ACPI_FAILURE (status)) {
163 			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X%8.8X, size %X\n",
164 					ACPI_FORMAT_UINT64 (address), (u32) window_size));
165 			mem_info->mapped_length = 0;
166 			return_ACPI_STATUS (status);
167 		}
168 
169 		/* Save the physical address and mapping size */
170 
171 		mem_info->mapped_physical_address = address;
172 		mem_info->mapped_length = window_size;
173 	}
174 
175 	/*
176 	 * Generate a logical pointer corresponding to the address we want to
177 	 * access
178 	 */
179 	logical_addr_ptr = mem_info->mapped_logical_address +
180 			  ((acpi_integer) address - (acpi_integer) mem_info->mapped_physical_address);
181 
182 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
183 			"system_memory %d (%d width) Address=%8.8X%8.8X\n", function, bit_width,
184 			ACPI_FORMAT_UINT64 (address)));
185 
186    /*
187 	* Perform the memory read or write
188 	*
189 	* Note: For machines that do not support non-aligned transfers, the target
190 	* address was checked for alignment above.  We do not attempt to break the
191 	* transfer up into smaller (byte-size) chunks because the AML specifically
192 	* asked for a transfer width that the hardware may require.
193 	*/
194 	switch (function) {
195 	case ACPI_READ:
196 
197 		*value = 0;
198 		switch (bit_width) {
199 		case 8:
200 			*value = (acpi_integer) *((u8 *) logical_addr_ptr);
201 			break;
202 
203 		case 16:
204 			*value = (acpi_integer) *((u16 *) logical_addr_ptr);
205 			break;
206 
207 		case 32:
208 			*value = (acpi_integer) *((u32 *) logical_addr_ptr);
209 			break;
210 
211 #if ACPI_MACHINE_WIDTH != 16
212 		case 64:
213 			*value = (acpi_integer) *((u64 *) logical_addr_ptr);
214 			break;
215 #endif
216 		default:
217 			/* bit_width was already validated */
218 			break;
219 		}
220 		break;
221 
222 	case ACPI_WRITE:
223 
224 		switch (bit_width) {
225 		case 8:
226 			*(u8 *) logical_addr_ptr = (u8) *value;
227 			break;
228 
229 		case 16:
230 			*(u16 *) logical_addr_ptr = (u16) *value;
231 			break;
232 
233 		case 32:
234 			*(u32 *) logical_addr_ptr = (u32) *value;
235 			break;
236 
237 #if ACPI_MACHINE_WIDTH != 16
238 		case 64:
239 			*(u64 *) logical_addr_ptr = (u64) *value;
240 			break;
241 #endif
242 
243 		default:
244 			/* bit_width was already validated */
245 			break;
246 		}
247 		break;
248 
249 	default:
250 		status = AE_BAD_PARAMETER;
251 		break;
252 	}
253 
254 	return_ACPI_STATUS (status);
255 }
256 
257 
258 /*******************************************************************************
259  *
260  * FUNCTION:    acpi_ex_system_io_space_handler
261  *
262  * PARAMETERS:  Function            - Read or Write operation
263  *              Address             - Where in the space to read or write
264  *              bit_width           - Field width in bits (8, 16, or 32)
265  *              Value               - Pointer to in or out value
266  *              handler_context     - Pointer to Handler's context
267  *              region_context      - Pointer to context specific to the
268  *                                    accessed region
269  *
270  * RETURN:      Status
271  *
272  * DESCRIPTION: Handler for the System IO address space (Op Region)
273  *
274  ******************************************************************************/
275 
276 acpi_status
acpi_ex_system_io_space_handler(u32 function,acpi_physical_address address,u32 bit_width,acpi_integer * value,void * handler_context,void * region_context)277 acpi_ex_system_io_space_handler (
278 	u32                             function,
279 	acpi_physical_address           address,
280 	u32                             bit_width,
281 	acpi_integer                    *value,
282 	void                            *handler_context,
283 	void                            *region_context)
284 {
285 	acpi_status                     status = AE_OK;
286 	u32                             value32;
287 
288 
289 	ACPI_FUNCTION_TRACE ("ex_system_io_space_handler");
290 
291 
292 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
293 			"system_iO %d (%d width) Address=%8.8X%8.8X\n", function, bit_width,
294 			ACPI_FORMAT_UINT64 (address)));
295 
296 	/* Decode the function parameter */
297 
298 	switch (function) {
299 	case ACPI_READ:
300 
301 		status = acpi_os_read_port ((acpi_io_address) address, &value32, bit_width);
302 		*value = value32;
303 		break;
304 
305 	case ACPI_WRITE:
306 
307 		status = acpi_os_write_port ((acpi_io_address) address, (u32) *value, bit_width);
308 		break;
309 
310 	default:
311 		status = AE_BAD_PARAMETER;
312 		break;
313 	}
314 
315 	return_ACPI_STATUS (status);
316 }
317 
318 
319 /*******************************************************************************
320  *
321  * FUNCTION:    acpi_ex_pci_config_space_handler
322  *
323  * PARAMETERS:  Function            - Read or Write operation
324  *              Address             - Where in the space to read or write
325  *              bit_width           - Field width in bits (8, 16, or 32)
326  *              Value               - Pointer to in or out value
327  *              handler_context     - Pointer to Handler's context
328  *              region_context      - Pointer to context specific to the
329  *                                    accessed region
330  *
331  * RETURN:      Status
332  *
333  * DESCRIPTION: Handler for the PCI Config address space (Op Region)
334  *
335  ******************************************************************************/
336 
337 acpi_status
acpi_ex_pci_config_space_handler(u32 function,acpi_physical_address address,u32 bit_width,acpi_integer * value,void * handler_context,void * region_context)338 acpi_ex_pci_config_space_handler (
339 	u32                             function,
340 	acpi_physical_address           address,
341 	u32                             bit_width,
342 	acpi_integer                    *value,
343 	void                            *handler_context,
344 	void                            *region_context)
345 {
346 	acpi_status                     status = AE_OK;
347 	struct acpi_pci_id              *pci_id;
348 	u16                             pci_register;
349 
350 
351 	ACPI_FUNCTION_TRACE ("ex_pci_config_space_handler");
352 
353 
354 	/*
355 	 *  The arguments to acpi_os(Read|Write)pci_configuration are:
356 	 *
357 	 *  pci_segment is the PCI bus segment range 0-31
358 	 *  pci_bus     is the PCI bus number range 0-255
359 	 *  pci_device  is the PCI device number range 0-31
360 	 *  pci_function is the PCI device function number
361 	 *  pci_register is the Config space register range 0-255 bytes
362 	 *
363 	 *  Value - input value for write, output address for read
364 	 *
365 	 */
366 	pci_id      = (struct acpi_pci_id *) region_context;
367 	pci_register = (u16) (u32) address;
368 
369 	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
370 		"pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
371 		function, bit_width, pci_id->segment, pci_id->bus, pci_id->device,
372 		pci_id->function, pci_register));
373 
374 	switch (function) {
375 	case ACPI_READ:
376 
377 		*value = 0;
378 		status = acpi_os_read_pci_configuration (pci_id, pci_register, value, bit_width);
379 		break;
380 
381 	case ACPI_WRITE:
382 
383 		status = acpi_os_write_pci_configuration (pci_id, pci_register, *value, bit_width);
384 		break;
385 
386 	default:
387 
388 		status = AE_BAD_PARAMETER;
389 		break;
390 	}
391 
392 	return_ACPI_STATUS (status);
393 }
394 
395 
396 /*******************************************************************************
397  *
398  * FUNCTION:    acpi_ex_cmos_space_handler
399  *
400  * PARAMETERS:  Function            - Read or Write operation
401  *              Address             - Where in the space to read or write
402  *              bit_width           - Field width in bits (8, 16, or 32)
403  *              Value               - Pointer to in or out value
404  *              handler_context     - Pointer to Handler's context
405  *              region_context      - Pointer to context specific to the
406  *                                    accessed region
407  *
408  * RETURN:      Status
409  *
410  * DESCRIPTION: Handler for the CMOS address space (Op Region)
411  *
412  ******************************************************************************/
413 
414 acpi_status
acpi_ex_cmos_space_handler(u32 function,acpi_physical_address address,u32 bit_width,acpi_integer * value,void * handler_context,void * region_context)415 acpi_ex_cmos_space_handler (
416 	u32                             function,
417 	acpi_physical_address           address,
418 	u32                             bit_width,
419 	acpi_integer                    *value,
420 	void                            *handler_context,
421 	void                            *region_context)
422 {
423 	acpi_status                     status = AE_OK;
424 
425 
426 	ACPI_FUNCTION_TRACE ("ex_cmos_space_handler");
427 
428 
429 	return_ACPI_STATUS (status);
430 }
431 
432 
433 /*******************************************************************************
434  *
435  * FUNCTION:    acpi_ex_pci_bar_space_handler
436  *
437  * PARAMETERS:  Function            - Read or Write operation
438  *              Address             - Where in the space to read or write
439  *              bit_width           - Field width in bits (8, 16, or 32)
440  *              Value               - Pointer to in or out value
441  *              handler_context     - Pointer to Handler's context
442  *              region_context      - Pointer to context specific to the
443  *                                    accessed region
444  *
445  * RETURN:      Status
446  *
447  * DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
448  *
449  ******************************************************************************/
450 
451 acpi_status
acpi_ex_pci_bar_space_handler(u32 function,acpi_physical_address address,u32 bit_width,acpi_integer * value,void * handler_context,void * region_context)452 acpi_ex_pci_bar_space_handler (
453 	u32                             function,
454 	acpi_physical_address           address,
455 	u32                             bit_width,
456 	acpi_integer                    *value,
457 	void                            *handler_context,
458 	void                            *region_context)
459 {
460 	acpi_status                     status = AE_OK;
461 
462 
463 	ACPI_FUNCTION_TRACE ("ex_pci_bar_space_handler");
464 
465 
466 	return_ACPI_STATUS (status);
467 }
468 
469 
470 /*******************************************************************************
471  *
472  * FUNCTION:    acpi_ex_data_table_space_handler
473  *
474  * PARAMETERS:  Function            - Read or Write operation
475  *              Address             - Where in the space to read or write
476  *              bit_width           - Field width in bits (8, 16, or 32)
477  *              Value               - Pointer to in or out value
478  *              handler_context     - Pointer to Handler's context
479  *              region_context      - Pointer to context specific to the
480  *                                    accessed region
481  *
482  * RETURN:      Status
483  *
484  * DESCRIPTION: Handler for the Data Table address space (Op Region)
485  *
486  ******************************************************************************/
487 
488 acpi_status
acpi_ex_data_table_space_handler(u32 function,acpi_physical_address address,u32 bit_width,acpi_integer * value,void * handler_context,void * region_context)489 acpi_ex_data_table_space_handler (
490 	u32                             function,
491 	acpi_physical_address           address,
492 	u32                             bit_width,
493 	acpi_integer                    *value,
494 	void                            *handler_context,
495 	void                            *region_context)
496 {
497 	acpi_status                     status = AE_OK;
498 	u32                             byte_width = ACPI_DIV_8 (bit_width);
499 	u32                             i;
500 	char                            *logical_addr_ptr;
501 
502 
503 	ACPI_FUNCTION_TRACE ("ex_data_table_space_handler");
504 
505 
506 	logical_addr_ptr = ACPI_PHYSADDR_TO_PTR (address);
507 
508 
509    /* Perform the memory read or write */
510 
511 	switch (function) {
512 	case ACPI_READ:
513 
514 		for (i = 0; i < byte_width; i++) {
515 			((char *) value) [i] = logical_addr_ptr[i];
516 		}
517 		break;
518 
519 	case ACPI_WRITE:
520 	default:
521 
522 		return_ACPI_STATUS (AE_SUPPORT);
523 	}
524 
525 	return_ACPI_STATUS (status);
526 }
527 
528 
529