1
2/******************************************************************************
3 *
4 * Module Name: exregion - ACPI default op_region (address space) handlers
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2007, 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#include <acpi/acpi.h>
46#include <acpi/acinterp.h>
47
48#define _COMPONENT          ACPI_EXECUTER
49ACPI_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 ******************************************************************************/
68acpi_status
69acpi_ex_system_memory_space_handler(u32 function,
70				    acpi_physical_address address,
71				    u32 bit_width,
72				    acpi_integer * 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 window_size;
80#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
81	u32 remainder;
82#endif
83
84	ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
85
86	/* Validate and translate the bit width */
87
88	switch (bit_width) {
89	case 8:
90		length = 1;
91		break;
92
93	case 16:
94		length = 2;
95		break;
96
97	case 32:
98		length = 4;
99		break;
100
101	case 64:
102		length = 8;
103		break;
104
105	default:
106		ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %d",
107			    bit_width));
108		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
109	}
110
111#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
112	/*
113	 * Hardware does not support non-aligned data transfers, we must verify
114	 * the request.
115	 */
116	(void)acpi_ut_short_divide((acpi_integer) address, length, NULL,
117				   &remainder);
118	if (remainder != 0) {
119		return_ACPI_STATUS(AE_AML_ALIGNMENT);
120	}
121#endif
122
123	/*
124	 * Does the request fit into the cached memory mapping?
125	 * Is 1) Address below the current mapping? OR
126	 *    2) Address beyond the current mapping?
127	 */
128	if ((address < mem_info->mapped_physical_address) ||
129	    (((acpi_integer) address + length) > ((acpi_integer)
130						  mem_info->
131						  mapped_physical_address +
132						  mem_info->mapped_length))) {
133		/*
134		 * The request cannot be resolved by the current memory mapping;
135		 * Delete the existing mapping and create a new one.
136		 */
137		if (mem_info->mapped_length) {
138
139			/* Valid mapping, delete it */
140
141			acpi_os_unmap_memory(mem_info->mapped_logical_address,
142					     mem_info->mapped_length);
143		}
144
145		/*
146		 * Don't attempt to map memory beyond the end of the region, and
147		 * constrain the maximum mapping size to something reasonable.
148		 */
149		window_size = (acpi_size)
150		    ((mem_info->address + mem_info->length) - address);
151
152		if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) {
153			window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE;
154		}
155
156		/* Create a new mapping starting at the address given */
157
158		mem_info->mapped_logical_address =
159		    acpi_os_map_memory((acpi_native_uint) address, window_size);
160		if (!mem_info->mapped_logical_address) {
161			ACPI_ERROR((AE_INFO,
162				    "Could not map memory at %8.8X%8.8X, size %X",
163				    ACPI_FORMAT_UINT64(address),
164				    (u32) window_size));
165			mem_info->mapped_length = 0;
166			return_ACPI_STATUS(AE_NO_MEMORY);
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 -
181	     (acpi_integer) mem_info->mapped_physical_address);
182
183	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
184			  "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n",
185			  bit_width, function, ACPI_FORMAT_UINT64(address)));
186
187	/*
188	 * Perform the memory read or write
189	 *
190	 * Note: For machines that do not support non-aligned transfers, the target
191	 * address was checked for alignment above.  We do not attempt to break the
192	 * transfer up into smaller (byte-size) chunks because the AML specifically
193	 * asked for a transfer width that the hardware may require.
194	 */
195	switch (function) {
196	case ACPI_READ:
197
198		*value = 0;
199		switch (bit_width) {
200		case 8:
201			*value = (acpi_integer) ACPI_GET8(logical_addr_ptr);
202			break;
203
204		case 16:
205			*value = (acpi_integer) ACPI_GET16(logical_addr_ptr);
206			break;
207
208		case 32:
209			*value = (acpi_integer) ACPI_GET32(logical_addr_ptr);
210			break;
211
212		case 64:
213			*value = (acpi_integer) ACPI_GET64(logical_addr_ptr);
214			break;
215
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			ACPI_SET8(logical_addr_ptr) = (u8) * value;
227			break;
228
229		case 16:
230			ACPI_SET16(logical_addr_ptr) = (u16) * value;
231			break;
232
233		case 32:
234			ACPI_SET32(logical_addr_ptr) = (u32) * value;
235			break;
236
237		case 64:
238			ACPI_SET64(logical_addr_ptr) = (u64) * value;
239			break;
240
241		default:
242			/* bit_width was already validated */
243			break;
244		}
245		break;
246
247	default:
248		status = AE_BAD_PARAMETER;
249		break;
250	}
251
252	return_ACPI_STATUS(status);
253}
254
255/*******************************************************************************
256 *
257 * FUNCTION:    acpi_ex_system_io_space_handler
258 *
259 * PARAMETERS:  Function            - Read or Write operation
260 *              Address             - Where in the space to read or write
261 *              bit_width           - Field width in bits (8, 16, or 32)
262 *              Value               - Pointer to in or out value
263 *              handler_context     - Pointer to Handler's context
264 *              region_context      - Pointer to context specific to the
265 *                                    accessed region
266 *
267 * RETURN:      Status
268 *
269 * DESCRIPTION: Handler for the System IO address space (Op Region)
270 *
271 ******************************************************************************/
272
273acpi_status
274acpi_ex_system_io_space_handler(u32 function,
275				acpi_physical_address address,
276				u32 bit_width,
277				acpi_integer * value,
278				void *handler_context, void *region_context)
279{
280	acpi_status status = AE_OK;
281	u32 value32;
282
283	ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
284
285	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
286			  "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n",
287			  bit_width, function, ACPI_FORMAT_UINT64(address)));
288
289	/* Decode the function parameter */
290
291	switch (function) {
292	case ACPI_READ:
293
294		status = acpi_os_read_port((acpi_io_address) address,
295					   &value32, bit_width);
296		*value = value32;
297		break;
298
299	case ACPI_WRITE:
300
301		status = acpi_os_write_port((acpi_io_address) address,
302					    (u32) * value, bit_width);
303		break;
304
305	default:
306		status = AE_BAD_PARAMETER;
307		break;
308	}
309
310	return_ACPI_STATUS(status);
311}
312
313/*******************************************************************************
314 *
315 * FUNCTION:    acpi_ex_pci_config_space_handler
316 *
317 * PARAMETERS:  Function            - Read or Write operation
318 *              Address             - Where in the space to read or write
319 *              bit_width           - Field width in bits (8, 16, or 32)
320 *              Value               - Pointer to in or out value
321 *              handler_context     - Pointer to Handler's context
322 *              region_context      - Pointer to context specific to the
323 *                                    accessed region
324 *
325 * RETURN:      Status
326 *
327 * DESCRIPTION: Handler for the PCI Config address space (Op Region)
328 *
329 ******************************************************************************/
330
331acpi_status
332acpi_ex_pci_config_space_handler(u32 function,
333				 acpi_physical_address address,
334				 u32 bit_width,
335				 acpi_integer * value,
336				 void *handler_context, void *region_context)
337{
338	acpi_status status = AE_OK;
339	struct acpi_pci_id *pci_id;
340	u16 pci_register;
341
342	ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
343
344	/*
345	 *  The arguments to acpi_os(Read|Write)pci_configuration are:
346	 *
347	 *  pci_segment is the PCI bus segment range 0-31
348	 *  pci_bus     is the PCI bus number range 0-255
349	 *  pci_device  is the PCI device number range 0-31
350	 *  pci_function is the PCI device function number
351	 *  pci_register is the Config space register range 0-255 bytes
352	 *
353	 *  Value - input value for write, output address for read
354	 *
355	 */
356	pci_id = (struct acpi_pci_id *)region_context;
357	pci_register = (u16) (u32) address;
358
359	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
360			  "Pci-Config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
361			  function, bit_width, pci_id->segment, pci_id->bus,
362			  pci_id->device, pci_id->function, pci_register));
363
364	switch (function) {
365	case ACPI_READ:
366
367		*value = 0;
368		status = acpi_os_read_pci_configuration(pci_id, pci_register,
369							value, bit_width);
370		break;
371
372	case ACPI_WRITE:
373
374		status = acpi_os_write_pci_configuration(pci_id, pci_register,
375							 *value, bit_width);
376		break;
377
378	default:
379
380		status = AE_BAD_PARAMETER;
381		break;
382	}
383
384	return_ACPI_STATUS(status);
385}
386
387/*******************************************************************************
388 *
389 * FUNCTION:    acpi_ex_cmos_space_handler
390 *
391 * PARAMETERS:  Function            - Read or Write operation
392 *              Address             - Where in the space to read or write
393 *              bit_width           - Field width in bits (8, 16, or 32)
394 *              Value               - Pointer to in or out value
395 *              handler_context     - Pointer to Handler's context
396 *              region_context      - Pointer to context specific to the
397 *                                    accessed region
398 *
399 * RETURN:      Status
400 *
401 * DESCRIPTION: Handler for the CMOS address space (Op Region)
402 *
403 ******************************************************************************/
404
405acpi_status
406acpi_ex_cmos_space_handler(u32 function,
407			   acpi_physical_address address,
408			   u32 bit_width,
409			   acpi_integer * value,
410			   void *handler_context, void *region_context)
411{
412	acpi_status status = AE_OK;
413
414	ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
415
416	return_ACPI_STATUS(status);
417}
418
419/*******************************************************************************
420 *
421 * FUNCTION:    acpi_ex_pci_bar_space_handler
422 *
423 * PARAMETERS:  Function            - Read or Write operation
424 *              Address             - Where in the space to read or write
425 *              bit_width           - Field width in bits (8, 16, or 32)
426 *              Value               - Pointer to in or out value
427 *              handler_context     - Pointer to Handler's context
428 *              region_context      - Pointer to context specific to the
429 *                                    accessed region
430 *
431 * RETURN:      Status
432 *
433 * DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
434 *
435 ******************************************************************************/
436
437acpi_status
438acpi_ex_pci_bar_space_handler(u32 function,
439			      acpi_physical_address address,
440			      u32 bit_width,
441			      acpi_integer * value,
442			      void *handler_context, void *region_context)
443{
444	acpi_status status = AE_OK;
445
446	ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
447
448	return_ACPI_STATUS(status);
449}
450
451/*******************************************************************************
452 *
453 * FUNCTION:    acpi_ex_data_table_space_handler
454 *
455 * PARAMETERS:  Function            - Read or Write operation
456 *              Address             - Where in the space to read or write
457 *              bit_width           - Field width in bits (8, 16, or 32)
458 *              Value               - Pointer to in or out value
459 *              handler_context     - Pointer to Handler's context
460 *              region_context      - Pointer to context specific to the
461 *                                    accessed region
462 *
463 * RETURN:      Status
464 *
465 * DESCRIPTION: Handler for the Data Table address space (Op Region)
466 *
467 ******************************************************************************/
468
469acpi_status
470acpi_ex_data_table_space_handler(u32 function,
471				 acpi_physical_address address,
472				 u32 bit_width,
473				 acpi_integer * value,
474				 void *handler_context, void *region_context)
475{
476	ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
477
478	/* Perform the memory read or write */
479
480	switch (function) {
481	case ACPI_READ:
482
483		ACPI_MEMCPY(ACPI_CAST_PTR(char, value),
484			    ACPI_PHYSADDR_TO_PTR(address),
485			    ACPI_DIV_8(bit_width));
486		break;
487
488	case ACPI_WRITE:
489	default:
490
491		return_ACPI_STATUS(AE_SUPPORT);
492	}
493
494	return_ACPI_STATUS(AE_OK);
495}
496