ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / acpi / executer / exregion.c
1
2 /******************************************************************************
3  *
4  * Module Name: exregion - ACPI default op_region (address space) handlers
5  *
6  *****************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2004, 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