exregion.c 14.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8

/******************************************************************************
 *
 * Module Name: exregion - ACPI default op_region (address space) handlers
 *
 *****************************************************************************/

/*
L
Len Brown 已提交
9
 * Copyright (C) 2000 - 2008, Intel Corp.
L
Linus Torvalds 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

#include <acpi/acpi.h>
46
#include <acpi/accommon.h>
L
Linus Torvalds 已提交
47 48 49
#include <acpi/acinterp.h>

#define _COMPONENT          ACPI_EXECUTER
L
Len Brown 已提交
50
ACPI_MODULE_NAME("exregion")
L
Linus Torvalds 已提交
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_system_memory_space_handler
 *
 * PARAMETERS:  Function            - Read or Write operation
 *              Address             - Where in the space to read or write
 *              bit_width           - Field width in bits (8, 16, or 32)
 *              Value               - Pointer to in or out value
 *              handler_context     - Pointer to Handler's context
 *              region_context      - Pointer to context specific to the
 *                                    accessed region
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Handler for the System Memory address space (Op Region)
 *
 ******************************************************************************/
acpi_status
L
Len Brown 已提交
70 71 72 73 74
acpi_ex_system_memory_space_handler(u32 function,
				    acpi_physical_address address,
				    u32 bit_width,
				    acpi_integer * value,
				    void *handler_context, void *region_context)
L
Linus Torvalds 已提交
75
{
L
Len Brown 已提交
76 77 78 79 80
	acpi_status status = AE_OK;
	void *logical_addr_ptr = NULL;
	struct acpi_mem_space_context *mem_info = region_context;
	u32 length;
	acpi_size window_size;
B
Bob Moore 已提交
81
#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
L
Len Brown 已提交
82
	u32 remainder;
L
Linus Torvalds 已提交
83 84
#endif

B
Bob Moore 已提交
85
	ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
L
Linus Torvalds 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

	/* Validate and translate the bit width */

	switch (bit_width) {
	case 8:
		length = 1;
		break;

	case 16:
		length = 2;
		break;

	case 32:
		length = 4;
		break;

	case 64:
		length = 8;
		break;

	default:
B
Bob Moore 已提交
107
		ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %d",
B
Bob Moore 已提交
108
			    bit_width));
L
Len Brown 已提交
109
		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
L
Linus Torvalds 已提交
110 111
	}

B
Bob Moore 已提交
112
#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
L
Linus Torvalds 已提交
113 114 115 116
	/*
	 * Hardware does not support non-aligned data transfers, we must verify
	 * the request.
	 */
L
Len Brown 已提交
117 118
	(void)acpi_ut_short_divide((acpi_integer) address, length, NULL,
				   &remainder);
L
Linus Torvalds 已提交
119
	if (remainder != 0) {
L
Len Brown 已提交
120
		return_ACPI_STATUS(AE_AML_ALIGNMENT);
L
Linus Torvalds 已提交
121 122 123 124 125 126 127 128 129
	}
#endif

	/*
	 * Does the request fit into the cached memory mapping?
	 * Is 1) Address below the current mapping? OR
	 *    2) Address beyond the current mapping?
	 */
	if ((address < mem_info->mapped_physical_address) ||
L
Len Brown 已提交
130 131 132 133
	    (((acpi_integer) address + length) > ((acpi_integer)
						  mem_info->
						  mapped_physical_address +
						  mem_info->mapped_length))) {
L
Linus Torvalds 已提交
134 135 136 137 138
		/*
		 * The request cannot be resolved by the current memory mapping;
		 * Delete the existing mapping and create a new one.
		 */
		if (mem_info->mapped_length) {
B
Bob Moore 已提交
139

L
Linus Torvalds 已提交
140 141
			/* Valid mapping, delete it */

L
Len Brown 已提交
142 143
			acpi_os_unmap_memory(mem_info->mapped_logical_address,
					     mem_info->mapped_length);
L
Linus Torvalds 已提交
144 145 146 147 148 149
		}

		/*
		 * Don't attempt to map memory beyond the end of the region, and
		 * constrain the maximum mapping size to something reasonable.
		 */
R
Robert Moore 已提交
150
		window_size = (acpi_size)
L
Len Brown 已提交
151
		    ((mem_info->address + mem_info->length) - address);
R
Robert Moore 已提交
152

L
Linus Torvalds 已提交
153 154 155 156 157 158
		if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) {
			window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE;
		}

		/* Create a new mapping starting at the address given */

159
		mem_info->mapped_logical_address =
160
			acpi_os_map_memory((acpi_physical_address) address, window_size);
161
		if (!mem_info->mapped_logical_address) {
B
Bob Moore 已提交
162 163
			ACPI_ERROR((AE_INFO,
				    "Could not map memory at %8.8X%8.8X, size %X",
164
				    ACPI_FORMAT_NATIVE_UINT(address),
B
Bob Moore 已提交
165
				    (u32) window_size));
L
Linus Torvalds 已提交
166
			mem_info->mapped_length = 0;
167
			return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
168 169 170 171 172 173 174 175 176 177 178 179 180
		}

		/* Save the physical address and mapping size */

		mem_info->mapped_physical_address = address;
		mem_info->mapped_length = window_size;
	}

	/*
	 * Generate a logical pointer corresponding to the address we want to
	 * access
	 */
	logical_addr_ptr = mem_info->mapped_logical_address +
L
Len Brown 已提交
181 182 183 184
	    ((acpi_integer) address -
	     (acpi_integer) mem_info->mapped_physical_address);

	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
B
Bob Moore 已提交
185
			  "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n",
186 187
			  bit_width, function,
			  ACPI_FORMAT_NATIVE_UINT(address)));
L
Len Brown 已提交
188 189 190 191 192 193 194 195 196

	/*
	 * Perform the memory read or write
	 *
	 * Note: For machines that do not support non-aligned transfers, the target
	 * address was checked for alignment above.  We do not attempt to break the
	 * transfer up into smaller (byte-size) chunks because the AML specifically
	 * asked for a transfer width that the hardware may require.
	 */
L
Linus Torvalds 已提交
197 198 199 200 201 202
	switch (function) {
	case ACPI_READ:

		*value = 0;
		switch (bit_width) {
		case 8:
B
Bob Moore 已提交
203
			*value = (acpi_integer) ACPI_GET8(logical_addr_ptr);
L
Linus Torvalds 已提交
204 205 206
			break;

		case 16:
B
Bob Moore 已提交
207
			*value = (acpi_integer) ACPI_GET16(logical_addr_ptr);
L
Linus Torvalds 已提交
208 209 210
			break;

		case 32:
B
Bob Moore 已提交
211
			*value = (acpi_integer) ACPI_GET32(logical_addr_ptr);
L
Linus Torvalds 已提交
212 213 214
			break;

		case 64:
B
Bob Moore 已提交
215
			*value = (acpi_integer) ACPI_GET64(logical_addr_ptr);
L
Linus Torvalds 已提交
216
			break;
B
Bob Moore 已提交
217

L
Linus Torvalds 已提交
218 219 220 221 222 223 224 225 226 227
		default:
			/* bit_width was already validated */
			break;
		}
		break;

	case ACPI_WRITE:

		switch (bit_width) {
		case 8:
B
Bob Moore 已提交
228
			ACPI_SET8(logical_addr_ptr) = (u8) * value;
L
Linus Torvalds 已提交
229 230 231
			break;

		case 16:
B
Bob Moore 已提交
232
			ACPI_SET16(logical_addr_ptr) = (u16) * value;
L
Linus Torvalds 已提交
233 234 235
			break;

		case 32:
B
Bob Moore 已提交
236
			ACPI_SET32(logical_addr_ptr) = (u32) * value;
L
Linus Torvalds 已提交
237 238 239
			break;

		case 64:
B
Bob Moore 已提交
240
			ACPI_SET64(logical_addr_ptr) = (u64) * value;
L
Linus Torvalds 已提交
241 242 243 244 245 246 247 248 249 250 251 252 253
			break;

		default:
			/* bit_width was already validated */
			break;
		}
		break;

	default:
		status = AE_BAD_PARAMETER;
		break;
	}

L
Len Brown 已提交
254
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_system_io_space_handler
 *
 * PARAMETERS:  Function            - Read or Write operation
 *              Address             - Where in the space to read or write
 *              bit_width           - Field width in bits (8, 16, or 32)
 *              Value               - Pointer to in or out value
 *              handler_context     - Pointer to Handler's context
 *              region_context      - Pointer to context specific to the
 *                                    accessed region
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Handler for the System IO address space (Op Region)
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
276 277 278 279 280
acpi_ex_system_io_space_handler(u32 function,
				acpi_physical_address address,
				u32 bit_width,
				acpi_integer * value,
				void *handler_context, void *region_context)
L
Linus Torvalds 已提交
281
{
L
Len Brown 已提交
282 283
	acpi_status status = AE_OK;
	u32 value32;
L
Linus Torvalds 已提交
284

B
Bob Moore 已提交
285
	ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
L
Linus Torvalds 已提交
286

L
Len Brown 已提交
287
	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
B
Bob Moore 已提交
288
			  "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n",
289 290
			  bit_width, function,
			  ACPI_FORMAT_NATIVE_UINT(address)));
L
Linus Torvalds 已提交
291 292 293 294 295 296

	/* Decode the function parameter */

	switch (function) {
	case ACPI_READ:

L
Len Brown 已提交
297 298
		status = acpi_os_read_port((acpi_io_address) address,
					   &value32, bit_width);
L
Linus Torvalds 已提交
299 300 301 302 303
		*value = value32;
		break;

	case ACPI_WRITE:

L
Len Brown 已提交
304 305
		status = acpi_os_write_port((acpi_io_address) address,
					    (u32) * value, bit_width);
L
Linus Torvalds 已提交
306 307 308 309 310 311 312
		break;

	default:
		status = AE_BAD_PARAMETER;
		break;
	}

L
Len Brown 已提交
313
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_pci_config_space_handler
 *
 * PARAMETERS:  Function            - Read or Write operation
 *              Address             - Where in the space to read or write
 *              bit_width           - Field width in bits (8, 16, or 32)
 *              Value               - Pointer to in or out value
 *              handler_context     - Pointer to Handler's context
 *              region_context      - Pointer to context specific to the
 *                                    accessed region
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Handler for the PCI Config address space (Op Region)
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
335 336 337 338 339
acpi_ex_pci_config_space_handler(u32 function,
				 acpi_physical_address address,
				 u32 bit_width,
				 acpi_integer * value,
				 void *handler_context, void *region_context)
L
Linus Torvalds 已提交
340
{
L
Len Brown 已提交
341 342 343
	acpi_status status = AE_OK;
	struct acpi_pci_id *pci_id;
	u16 pci_register;
M
Ming Lin 已提交
344
	u32 value32;
L
Linus Torvalds 已提交
345

B
Bob Moore 已提交
346
	ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
L
Linus Torvalds 已提交
347 348 349 350 351 352 353 354 355 356 357 358 359

	/*
	 *  The arguments to acpi_os(Read|Write)pci_configuration are:
	 *
	 *  pci_segment is the PCI bus segment range 0-31
	 *  pci_bus     is the PCI bus number range 0-255
	 *  pci_device  is the PCI device number range 0-31
	 *  pci_function is the PCI device function number
	 *  pci_register is the Config space register range 0-255 bytes
	 *
	 *  Value - input value for write, output address for read
	 *
	 */
L
Len Brown 已提交
360
	pci_id = (struct acpi_pci_id *)region_context;
L
Linus Torvalds 已提交
361 362
	pci_register = (u16) (u32) address;

L
Len Brown 已提交
363
	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
B
Bob Moore 已提交
364
			  "Pci-Config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
L
Len Brown 已提交
365 366
			  function, bit_width, pci_id->segment, pci_id->bus,
			  pci_id->device, pci_id->function, pci_register));
L
Linus Torvalds 已提交
367 368 369 370

	switch (function) {
	case ACPI_READ:

L
Len Brown 已提交
371
		status = acpi_os_read_pci_configuration(pci_id, pci_register,
M
Ming Lin 已提交
372 373
							&value32, bit_width);
		*value = value32;
L
Linus Torvalds 已提交
374 375 376 377
		break;

	case ACPI_WRITE:

L
Len Brown 已提交
378 379
		status = acpi_os_write_pci_configuration(pci_id, pci_register,
							 *value, bit_width);
L
Linus Torvalds 已提交
380 381 382 383 384 385 386 387
		break;

	default:

		status = AE_BAD_PARAMETER;
		break;
	}

L
Len Brown 已提交
388
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_cmos_space_handler
 *
 * PARAMETERS:  Function            - Read or Write operation
 *              Address             - Where in the space to read or write
 *              bit_width           - Field width in bits (8, 16, or 32)
 *              Value               - Pointer to in or out value
 *              handler_context     - Pointer to Handler's context
 *              region_context      - Pointer to context specific to the
 *                                    accessed region
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Handler for the CMOS address space (Op Region)
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
410 411 412 413 414
acpi_ex_cmos_space_handler(u32 function,
			   acpi_physical_address address,
			   u32 bit_width,
			   acpi_integer * value,
			   void *handler_context, void *region_context)
L
Linus Torvalds 已提交
415
{
L
Len Brown 已提交
416
	acpi_status status = AE_OK;
L
Linus Torvalds 已提交
417

B
Bob Moore 已提交
418
	ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
L
Linus Torvalds 已提交
419

L
Len Brown 已提交
420
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_pci_bar_space_handler
 *
 * PARAMETERS:  Function            - Read or Write operation
 *              Address             - Where in the space to read or write
 *              bit_width           - Field width in bits (8, 16, or 32)
 *              Value               - Pointer to in or out value
 *              handler_context     - Pointer to Handler's context
 *              region_context      - Pointer to context specific to the
 *                                    accessed region
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
442 443 444 445 446
acpi_ex_pci_bar_space_handler(u32 function,
			      acpi_physical_address address,
			      u32 bit_width,
			      acpi_integer * value,
			      void *handler_context, void *region_context)
L
Linus Torvalds 已提交
447
{
L
Len Brown 已提交
448
	acpi_status status = AE_OK;
L
Linus Torvalds 已提交
449

B
Bob Moore 已提交
450
	ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
L
Linus Torvalds 已提交
451

L
Len Brown 已提交
452
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_data_table_space_handler
 *
 * PARAMETERS:  Function            - Read or Write operation
 *              Address             - Where in the space to read or write
 *              bit_width           - Field width in bits (8, 16, or 32)
 *              Value               - Pointer to in or out value
 *              handler_context     - Pointer to Handler's context
 *              region_context      - Pointer to context specific to the
 *                                    accessed region
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Handler for the Data Table address space (Op Region)
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
474 475 476 477 478
acpi_ex_data_table_space_handler(u32 function,
				 acpi_physical_address address,
				 u32 bit_width,
				 acpi_integer * value,
				 void *handler_context, void *region_context)
L
Linus Torvalds 已提交
479
{
B
Bob Moore 已提交
480
	ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
L
Linus Torvalds 已提交
481

R
Robert Moore 已提交
482
	/* Perform the memory read or write */
L
Linus Torvalds 已提交
483 484 485 486

	switch (function) {
	case ACPI_READ:

B
Bob Moore 已提交
487 488 489
		ACPI_MEMCPY(ACPI_CAST_PTR(char, value),
			    ACPI_PHYSADDR_TO_PTR(address),
			    ACPI_DIV_8(bit_width));
L
Linus Torvalds 已提交
490 491 492 493 494
		break;

	case ACPI_WRITE:
	default:

L
Len Brown 已提交
495
		return_ACPI_STATUS(AE_SUPPORT);
L
Linus Torvalds 已提交
496 497
	}

B
Bob Moore 已提交
498
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
499
}