File: /usr/src/linux/drivers/acpi/executer/exregion.c
1
2 /******************************************************************************
3 *
4 * Module Name: exregion - ACPI default Op_region (address space) handlers
5 * $Revision: 58 $
6 *
7 *****************************************************************************/
8
9 /*
10 * Copyright (C) 2000, 2001 R. Byron Moore
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27
28 #include "acpi.h"
29 #include "acinterp.h"
30 #include "amlcode.h"
31 #include "acnamesp.h"
32 #include "achware.h"
33 #include "acevents.h"
34
35
36 #define _COMPONENT ACPI_EXECUTER
37 MODULE_NAME ("exregion")
38
39
40 /*******************************************************************************
41 *
42 * FUNCTION: Acpi_ex_system_memory_space_handler
43 *
44 * PARAMETERS: Function - Read or Write operation
45 * Address - Where in the space to read or write
46 * Bit_width - Field width in bits (8, 16, or 32)
47 * Value - Pointer to in or out value
48 * Handler_context - Pointer to Handler's context
49 * Region_context - Pointer to context specific to the
50 * accessed region
51 *
52 * RETURN: Status
53 *
54 * DESCRIPTION: Handler for the System Memory address space (Op Region)
55 *
56 ******************************************************************************/
57
58 acpi_status
59 acpi_ex_system_memory_space_handler (
60 u32 function,
61 ACPI_PHYSICAL_ADDRESS address,
62 u32 bit_width,
63 u32 *value,
64 void *handler_context,
65 void *region_context)
66 {
67 acpi_status status = AE_OK;
68 void *logical_addr_ptr = NULL;
69 acpi_mem_space_context *mem_info = region_context;
70 u32 length;
71
72
73 FUNCTION_TRACE ("Ex_system_memory_space_handler");
74
75
76 /* Validate and translate the bit width */
77
78 switch (bit_width) {
79 case 8:
80 length = 1;
81 break;
82
83 case 16:
84 length = 2;
85 break;
86
87 case 32:
88 length = 4;
89 break;
90
91 default:
92 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid System_memory width %d\n",
93 bit_width));
94 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
95 break;
96 }
97
98
99 /*
100 * Does the request fit into the cached memory mapping?
101 * Is 1) Address below the current mapping? OR
102 * 2) Address beyond the current mapping?
103 */
104 if ((address < mem_info->mapped_physical_address) ||
105 (((acpi_integer) address + length) >
106 ((acpi_integer) mem_info->mapped_physical_address + mem_info->mapped_length))) {
107 /*
108 * The request cannot be resolved by the current memory mapping;
109 * Delete the existing mapping and create a new one.
110 */
111 if (mem_info->mapped_length) {
112 /* Valid mapping, delete it */
113
114 acpi_os_unmap_memory (mem_info->mapped_logical_address,
115 mem_info->mapped_length);
116 }
117
118 mem_info->mapped_length = 0; /* In case of failure below */
119
120 /* Create a new mapping starting at the address given */
121
122 status = acpi_os_map_memory (address, SYSMEM_REGION_WINDOW_SIZE,
123 (void **) &mem_info->mapped_logical_address);
124 if (ACPI_FAILURE (status)) {
125 return_ACPI_STATUS (status);
126 }
127
128 /* Save the physical address and mapping size */
129
130 mem_info->mapped_physical_address = address;
131 mem_info->mapped_length = SYSMEM_REGION_WINDOW_SIZE;
132 }
133
134
135 /*
136 * Generate a logical pointer corresponding to the address we want to
137 * access
138 */
139
140 /* TBD: should these pointers go to 64-bit in all cases ? */
141
142 logical_addr_ptr = mem_info->mapped_logical_address +
143 ((acpi_integer) address - (acpi_integer) mem_info->mapped_physical_address);
144
145 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
146 "IO %d (%d width) Address=%8.8lX%8.8lX\n", function, bit_width,
147 HIDWORD (address), LODWORD (address)));
148
149 /* Perform the memory read or write */
150
151 switch (function) {
152
153 case ACPI_READ_ADR_SPACE:
154
155 switch (bit_width) {
156 case 8:
157 *value = (u32)* (u8 *) logical_addr_ptr;
158 break;
159
160 case 16:
161 MOVE_UNALIGNED16_TO_32 (value, logical_addr_ptr);
162 break;
163
164 case 32:
165 MOVE_UNALIGNED32_TO_32 (value, logical_addr_ptr);
166 break;
167 }
168
169 break;
170
171
172 case ACPI_WRITE_ADR_SPACE:
173
174 switch (bit_width) {
175 case 8:
176 *(u8 *) logical_addr_ptr = (u8) *value;
177 break;
178
179 case 16:
180 MOVE_UNALIGNED16_TO_16 (logical_addr_ptr, value);
181 break;
182
183 case 32:
184 MOVE_UNALIGNED32_TO_32 (logical_addr_ptr, value);
185 break;
186 }
187
188 break;
189
190
191 default:
192 status = AE_BAD_PARAMETER;
193 break;
194 }
195
196 return_ACPI_STATUS (status);
197 }
198
199
200 /*******************************************************************************
201 *
202 * FUNCTION: Acpi_ex_system_io_space_handler
203 *
204 * PARAMETERS: Function - Read or Write operation
205 * Address - Where in the space to read or write
206 * Bit_width - Field width in bits (8, 16, or 32)
207 * Value - Pointer to in or out value
208 * Handler_context - Pointer to Handler's context
209 * Region_context - Pointer to context specific to the
210 * accessed region
211 *
212 * RETURN: Status
213 *
214 * DESCRIPTION: Handler for the System IO address space (Op Region)
215 *
216 ******************************************************************************/
217
218 acpi_status
219 acpi_ex_system_io_space_handler (
220 u32 function,
221 ACPI_PHYSICAL_ADDRESS address,
222 u32 bit_width,
223 u32 *value,
224 void *handler_context,
225 void *region_context)
226 {
227 acpi_status status = AE_OK;
228
229
230 FUNCTION_TRACE ("Ex_system_io_space_handler");
231
232
233 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
234 "IO %d (%d width) Address=%8.8lX%8.8lX\n", function, bit_width,
235 HIDWORD (address), LODWORD (address)));
236
237 /* Decode the function parameter */
238
239 switch (function) {
240
241 case ACPI_READ_ADR_SPACE:
242
243 *value = 0;
244 status = acpi_os_read_port ((ACPI_IO_ADDRESS) address, value, bit_width);
245 break;
246
247
248 case ACPI_WRITE_ADR_SPACE:
249
250 status = acpi_os_write_port ((ACPI_IO_ADDRESS) address, *value, bit_width);
251 break;
252
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_pci_config_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 PCI Config address space (Op Region)
278 *
279 ******************************************************************************/
280
281 acpi_status
282 acpi_ex_pci_config_space_handler (
283 u32 function,
284 ACPI_PHYSICAL_ADDRESS address,
285 u32 bit_width,
286 u32 *value,
287 void *handler_context,
288 void *region_context)
289 {
290 acpi_status status = AE_OK;
291 acpi_pci_id *pci_id;
292 u16 pci_register;
293
294
295 FUNCTION_TRACE ("Ex_pci_config_space_handler");
296
297
298 /*
299 * The arguments to Acpi_os(Read|Write)Pci_cfg(Byte|Word|Dword) are:
300 *
301 * Pci_segment is the PCI bus segment range 0-31
302 * Pci_bus is the PCI bus number range 0-255
303 * Pci_device is the PCI device number range 0-31
304 * Pci_function is the PCI device function number
305 * Pci_register is the Config space register range 0-255 bytes
306 *
307 * Value - input value for write, output address for read
308 *
309 */
310 pci_id = (acpi_pci_id *) region_context;
311 pci_register = (u16) address;
312
313 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
314 "IO %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
315 function, bit_width, pci_id->segment, pci_id->bus, pci_id->device,
316 pci_id->function, pci_register));
317
318 switch (function) {
319
320 case ACPI_READ_ADR_SPACE:
321
322 *value = 0;
323 status = acpi_os_read_pci_configuration (pci_id, pci_register, value, bit_width);
324 break;
325
326
327 case ACPI_WRITE_ADR_SPACE:
328
329 status = acpi_os_write_pci_configuration (pci_id, pci_register, *value, bit_width);
330 break;
331
332
333 default:
334
335 status = AE_BAD_PARAMETER;
336 break;
337 }
338
339 return_ACPI_STATUS (status);
340 }
341
342