Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | |
2 | /****************************************************************************** | |
3 | * | |
4 | * Module Name: exregion - ACPI default op_region (address space) handlers | |
5 | * | |
6 | *****************************************************************************/ | |
7 | ||
8 | /* | |
9 | * Copyright (C) 2000 - 2005, 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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 |