diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/acpi/executer/exregion.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/acpi/executer/exregion.c')
-rw-r--r-- | drivers/acpi/executer/exregion.c | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c new file mode 100644 index 000000000000..7cfd0684c70b --- /dev/null +++ b/drivers/acpi/executer/exregion.c | |||
@@ -0,0 +1,528 @@ | |||
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 | |||