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 | ||
1da177e4 LT |
118 | #ifndef ACPI_MISALIGNED_TRANSFERS |
119 | /* | |
120 | * Hardware does not support non-aligned data transfers, we must verify | |
121 | * the request. | |
122 | */ | |
123 | (void) acpi_ut_short_divide ((acpi_integer) address, length, NULL, &remainder); | |
124 | if (remainder != 0) { | |
125 | return_ACPI_STATUS (AE_AML_ALIGNMENT); | |
126 | } | |
127 | #endif | |
128 | ||
129 | /* | |
130 | * Does the request fit into the cached memory mapping? | |
131 | * Is 1) Address below the current mapping? OR | |
132 | * 2) Address beyond the current mapping? | |
133 | */ | |
134 | if ((address < mem_info->mapped_physical_address) || | |
135 | (((acpi_integer) address + length) > | |
44f6c012 RM |
136 | ((acpi_integer) |
137 | mem_info->mapped_physical_address + mem_info->mapped_length))) { | |
1da177e4 LT |
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 | */ | |
44f6c012 RM |
153 | window_size = (acpi_size) |
154 | ((mem_info->address + mem_info->length) - address); | |
155 | ||
1da177e4 LT |
156 | if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) { |
157 | window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE; | |
158 | } | |
159 | ||
160 | /* Create a new mapping starting at the address given */ | |
161 | ||
162 | status = acpi_os_map_memory (address, window_size, | |
163 | (void **) &mem_info->mapped_logical_address); | |
164 | if (ACPI_FAILURE (status)) { | |
44f6c012 RM |
165 | ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, |
166 | "Could not map memory at %8.8X%8.8X, size %X\n", | |
167 | ACPI_FORMAT_UINT64 (address), (u32) window_size)); | |
1da177e4 LT |
168 | mem_info->mapped_length = 0; |
169 | return_ACPI_STATUS (status); | |
170 | } | |
171 | ||
172 | /* Save the physical address and mapping size */ | |
173 | ||
174 | mem_info->mapped_physical_address = address; | |
175 | mem_info->mapped_length = window_size; | |
176 | } | |
177 | ||
178 | /* | |
179 | * Generate a logical pointer corresponding to the address we want to | |
180 | * access | |
181 | */ | |
182 | logical_addr_ptr = mem_info->mapped_logical_address + | |
44f6c012 RM |
183 | ((acpi_integer) address - |
184 | (acpi_integer) mem_info->mapped_physical_address); | |
1da177e4 LT |
185 | |
186 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | |
44f6c012 RM |
187 | "system_memory %d (%d width) Address=%8.8X%8.8X\n", |
188 | function, bit_width, | |
1da177e4 LT |
189 | ACPI_FORMAT_UINT64 (address))); |
190 | ||
191 | /* | |
192 | * Perform the memory read or write | |
193 | * | |
194 | * Note: For machines that do not support non-aligned transfers, the target | |
195 | * address was checked for alignment above. We do not attempt to break the | |
196 | * transfer up into smaller (byte-size) chunks because the AML specifically | |
197 | * asked for a transfer width that the hardware may require. | |
198 | */ | |
199 | switch (function) { | |
200 | case ACPI_READ: | |
201 | ||
202 | *value = 0; | |
203 | switch (bit_width) { | |
204 | case 8: | |
205 | *value = (acpi_integer) *((u8 *) logical_addr_ptr); | |
206 | break; | |
207 | ||
208 | case 16: | |
209 | *value = (acpi_integer) *((u16 *) logical_addr_ptr); | |
210 | break; | |
211 | ||
212 | case 32: | |
213 | *value = (acpi_integer) *((u32 *) logical_addr_ptr); | |
214 | break; | |
215 | ||
216 | #if ACPI_MACHINE_WIDTH != 16 | |
217 | case 64: | |
218 | *value = (acpi_integer) *((u64 *) logical_addr_ptr); | |
219 | break; | |
220 | #endif | |
221 | default: | |
222 | /* bit_width was already validated */ | |
223 | break; | |
224 | } | |
225 | break; | |
226 | ||
227 | case ACPI_WRITE: | |
228 | ||
229 | switch (bit_width) { | |
230 | case 8: | |
231 | *(u8 *) logical_addr_ptr = (u8) *value; | |
232 | break; | |
233 | ||
234 | case 16: | |
235 | *(u16 *) logical_addr_ptr = (u16) *value; | |
236 | break; | |
237 | ||
238 | case 32: | |
239 | *(u32 *) logical_addr_ptr = (u32) *value; | |
240 | break; | |
241 | ||
242 | #if ACPI_MACHINE_WIDTH != 16 | |
243 | case 64: | |
244 | *(u64 *) logical_addr_ptr = (u64) *value; | |
245 | break; | |
246 | #endif | |
247 | ||
248 | default: | |
249 | /* bit_width was already validated */ | |
250 | break; | |
251 | } | |
252 | break; | |
253 | ||
254 | default: | |
255 | status = AE_BAD_PARAMETER; | |
256 | break; | |
257 | } | |
258 | ||
259 | return_ACPI_STATUS (status); | |
260 | } | |
261 | ||
262 | ||
263 | /******************************************************************************* | |
264 | * | |
265 | * FUNCTION: acpi_ex_system_io_space_handler | |
266 | * | |
267 | * PARAMETERS: Function - Read or Write operation | |
268 | * Address - Where in the space to read or write | |
269 | * bit_width - Field width in bits (8, 16, or 32) | |
270 | * Value - Pointer to in or out value | |
271 | * handler_context - Pointer to Handler's context | |
272 | * region_context - Pointer to context specific to the | |
273 | * accessed region | |
274 | * | |
275 | * RETURN: Status | |
276 | * | |
277 | * DESCRIPTION: Handler for the System IO address space (Op Region) | |
278 | * | |
279 | ******************************************************************************/ | |
280 | ||
281 | acpi_status | |
282 | acpi_ex_system_io_space_handler ( | |
283 | u32 function, | |
284 | acpi_physical_address address, | |
285 | u32 bit_width, | |
286 | acpi_integer *value, | |
287 | void *handler_context, | |
288 | void *region_context) | |
289 | { | |
290 | acpi_status status = AE_OK; | |
291 | u32 value32; | |
292 | ||
293 | ||
294 | ACPI_FUNCTION_TRACE ("ex_system_io_space_handler"); | |
295 | ||
296 | ||
297 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | |
298 | "system_iO %d (%d width) Address=%8.8X%8.8X\n", function, bit_width, | |
299 | ACPI_FORMAT_UINT64 (address))); | |
300 | ||
301 | /* Decode the function parameter */ | |
302 | ||
303 | switch (function) { | |
304 | case ACPI_READ: | |
305 | ||
44f6c012 RM |
306 | status = acpi_os_read_port ((acpi_io_address) address, |
307 | &value32, bit_width); | |
1da177e4 LT |
308 | *value = value32; |
309 | break; | |
310 | ||
311 | case ACPI_WRITE: | |
312 | ||
44f6c012 RM |
313 | status = acpi_os_write_port ((acpi_io_address) address, |
314 | (u32) *value, bit_width); | |
1da177e4 LT |
315 | break; |
316 | ||
317 | default: | |
318 | status = AE_BAD_PARAMETER; | |
319 | break; | |
320 | } | |
321 | ||
322 | return_ACPI_STATUS (status); | |
323 | } | |
324 | ||
325 | ||
326 | /******************************************************************************* | |
327 | * | |
328 | * FUNCTION: acpi_ex_pci_config_space_handler | |
329 | * | |
330 | * PARAMETERS: Function - Read or Write operation | |
331 | * Address - Where in the space to read or write | |
332 | * bit_width - Field width in bits (8, 16, or 32) | |
333 | * Value - Pointer to in or out value | |
334 | * handler_context - Pointer to Handler's context | |
335 | * region_context - Pointer to context specific to the | |
336 | * accessed region | |
337 | * | |
338 | * RETURN: Status | |
339 | * | |
340 | * DESCRIPTION: Handler for the PCI Config address space (Op Region) | |
341 | * | |
342 | ******************************************************************************/ | |
343 | ||
344 | acpi_status | |
345 | acpi_ex_pci_config_space_handler ( | |
346 | u32 function, | |
347 | acpi_physical_address address, | |
348 | u32 bit_width, | |
349 | acpi_integer *value, | |
350 | void *handler_context, | |
351 | void *region_context) | |
352 | { | |
353 | acpi_status status = AE_OK; | |
354 | struct acpi_pci_id *pci_id; | |
355 | u16 pci_register; | |
356 | ||
357 | ||
358 | ACPI_FUNCTION_TRACE ("ex_pci_config_space_handler"); | |
359 | ||
360 | ||
361 | /* | |
362 | * The arguments to acpi_os(Read|Write)pci_configuration are: | |
363 | * | |
364 | * pci_segment is the PCI bus segment range 0-31 | |
365 | * pci_bus is the PCI bus number range 0-255 | |
366 | * pci_device is the PCI device number range 0-31 | |
367 | * pci_function is the PCI device function number | |
368 | * pci_register is the Config space register range 0-255 bytes | |
369 | * | |
370 | * Value - input value for write, output address for read | |
371 | * | |
372 | */ | |
373 | pci_id = (struct acpi_pci_id *) region_context; | |
374 | pci_register = (u16) (u32) address; | |
375 | ||
376 | ACPI_DEBUG_PRINT ((ACPI_DB_INFO, | |
377 | "pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n", | |
378 | function, bit_width, pci_id->segment, pci_id->bus, pci_id->device, | |
379 | pci_id->function, pci_register)); | |
380 | ||
381 | switch (function) { | |
382 | case ACPI_READ: | |
383 | ||
384 | *value = 0; | |
44f6c012 RM |
385 | status = acpi_os_read_pci_configuration (pci_id, pci_register, |
386 | value, bit_width); | |
1da177e4 LT |
387 | break; |
388 | ||
389 | case ACPI_WRITE: | |
390 | ||
44f6c012 RM |
391 | status = acpi_os_write_pci_configuration (pci_id, pci_register, |
392 | *value, bit_width); | |
1da177e4 LT |
393 | break; |
394 | ||
395 | default: | |
396 | ||
397 | status = AE_BAD_PARAMETER; | |
398 | break; | |
399 | } | |
400 | ||
401 | return_ACPI_STATUS (status); | |
402 | } | |
403 | ||
404 | ||
405 | /******************************************************************************* | |
406 | * | |
407 | * FUNCTION: acpi_ex_cmos_space_handler | |
408 | * | |
409 | * PARAMETERS: Function - Read or Write operation | |
410 | * Address - Where in the space to read or write | |
411 | * bit_width - Field width in bits (8, 16, or 32) | |
412 | * Value - Pointer to in or out value | |
413 | * handler_context - Pointer to Handler's context | |
414 | * region_context - Pointer to context specific to the | |
415 | * accessed region | |
416 | * | |
417 | * RETURN: Status | |
418 | * | |
419 | * DESCRIPTION: Handler for the CMOS address space (Op Region) | |
420 | * | |
421 | ******************************************************************************/ | |
422 | ||
423 | acpi_status | |
424 | acpi_ex_cmos_space_handler ( | |
425 | u32 function, | |
426 | acpi_physical_address address, | |
427 | u32 bit_width, | |
428 | acpi_integer *value, | |
429 | void *handler_context, | |
430 | void *region_context) | |
431 | { | |
432 | acpi_status status = AE_OK; | |
433 | ||
434 | ||
435 | ACPI_FUNCTION_TRACE ("ex_cmos_space_handler"); | |
436 | ||
437 | ||
438 | return_ACPI_STATUS (status); | |
439 | } | |
440 | ||
441 | ||
442 | /******************************************************************************* | |
443 | * | |
444 | * FUNCTION: acpi_ex_pci_bar_space_handler | |
445 | * | |
446 | * PARAMETERS: Function - Read or Write operation | |
447 | * Address - Where in the space to read or write | |
448 | * bit_width - Field width in bits (8, 16, or 32) | |
449 | * Value - Pointer to in or out value | |
450 | * handler_context - Pointer to Handler's context | |
451 | * region_context - Pointer to context specific to the | |
452 | * accessed region | |
453 | * | |
454 | * RETURN: Status | |
455 | * | |
456 | * DESCRIPTION: Handler for the PCI bar_target address space (Op Region) | |
457 | * | |
458 | ******************************************************************************/ | |
459 | ||
460 | acpi_status | |
461 | acpi_ex_pci_bar_space_handler ( | |
462 | u32 function, | |
463 | acpi_physical_address address, | |
464 | u32 bit_width, | |
465 | acpi_integer *value, | |
466 | void *handler_context, | |
467 | void *region_context) | |
468 | { | |
469 | acpi_status status = AE_OK; | |
470 | ||
471 | ||
472 | ACPI_FUNCTION_TRACE ("ex_pci_bar_space_handler"); | |
473 | ||
474 | ||
475 | return_ACPI_STATUS (status); | |
476 | } | |
477 | ||
478 | ||
479 | /******************************************************************************* | |
480 | * | |
481 | * FUNCTION: acpi_ex_data_table_space_handler | |
482 | * | |
483 | * PARAMETERS: Function - Read or Write operation | |
484 | * Address - Where in the space to read or write | |
485 | * bit_width - Field width in bits (8, 16, or 32) | |
486 | * Value - Pointer to in or out value | |
487 | * handler_context - Pointer to Handler's context | |
488 | * region_context - Pointer to context specific to the | |
489 | * accessed region | |
490 | * | |
491 | * RETURN: Status | |
492 | * | |
493 | * DESCRIPTION: Handler for the Data Table address space (Op Region) | |
494 | * | |
495 | ******************************************************************************/ | |
496 | ||
497 | acpi_status | |
498 | acpi_ex_data_table_space_handler ( | |
499 | u32 function, | |
500 | acpi_physical_address address, | |
501 | u32 bit_width, | |
502 | acpi_integer *value, | |
503 | void *handler_context, | |
504 | void *region_context) | |
505 | { | |
506 | acpi_status status = AE_OK; | |
507 | u32 byte_width = ACPI_DIV_8 (bit_width); | |
508 | u32 i; | |
509 | char *logical_addr_ptr; | |
510 | ||
511 | ||
512 | ACPI_FUNCTION_TRACE ("ex_data_table_space_handler"); | |
513 | ||
514 | ||
515 | logical_addr_ptr = ACPI_PHYSADDR_TO_PTR (address); | |
516 | ||
44f6c012 | 517 | /* Perform the memory read or write */ |
1da177e4 LT |
518 | |
519 | switch (function) { | |
520 | case ACPI_READ: | |
521 | ||
522 | for (i = 0; i < byte_width; i++) { | |
523 | ((char *) value) [i] = logical_addr_ptr[i]; | |
524 | } | |
525 | break; | |
526 | ||
527 | case ACPI_WRITE: | |
528 | default: | |
529 | ||
530 | return_ACPI_STATUS (AE_SUPPORT); | |
531 | } | |
532 | ||
533 | return_ACPI_STATUS (status); | |
534 | } | |
535 | ||
536 |