Merge trunk HEAD (r46369)
[reactos.git] / reactos / drivers / bus / acpi / executer / amregion.c
1
2 /******************************************************************************
3 *
4 * Module Name: amregion - ACPI default Op_region (address space) handlers
5 * $Revision: 1.1 $
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
30
31
32 #define _COMPONENT ACPI_EXECUTER
33 MODULE_NAME ("amregion")
34
35
36 /*******************************************************************************
37 *
38 * FUNCTION: Acpi_aml_system_memory_space_handler
39 *
40 * PARAMETERS: Function - Read or Write operation
41 * Address - Where in the space to read or write
42 * Bit_width - Field width in bits (8, 16, or 32)
43 * Value - Pointer to in or out value
44 * Handler_context - Pointer to Handler's context
45 * Region_context - Pointer to context specific to the
46 * accessed region
47 *
48 * RETURN: Status
49 *
50 * DESCRIPTION: Handler for the System Memory address space (Op Region)
51 *
52 ******************************************************************************/
53
54 ACPI_STATUS
55 acpi_aml_system_memory_space_handler (
56 u32 function,
57 ACPI_PHYSICAL_ADDRESS address,
58 u32 bit_width,
59 u32 *value,
60 void *handler_context,
61 void *region_context)
62 {
63 ACPI_STATUS status = AE_OK;
64 void *logical_addr_ptr = NULL;
65 MEM_HANDLER_CONTEXT *mem_info = region_context;
66 u32 length;
67
68
69 /* Validate and translate the bit width */
70
71 switch (bit_width) {
72 case 8:
73 length = 1;
74 break;
75
76 case 16:
77 length = 2;
78 break;
79
80 case 32:
81 length = 4;
82 break;
83
84 default:
85 return (AE_AML_OPERAND_VALUE);
86 break;
87 }
88
89
90 /*
91 * Does the request fit into the cached memory mapping?
92 * Is 1) Address below the current mapping? OR
93 * 2) Address beyond the current mapping?
94 */
95
96 if ((address < mem_info->mapped_physical_address) ||
97 (((ACPI_INTEGER) address + length) >
98 ((ACPI_INTEGER) mem_info->mapped_physical_address + mem_info->mapped_length))) {
99 /*
100 * The request cannot be resolved by the current memory mapping;
101 * Delete the existing mapping and create a new one.
102 */
103
104 if (mem_info->mapped_length) {
105 /* Valid mapping, delete it */
106
107 acpi_os_unmap_memory (mem_info->mapped_logical_address,
108 mem_info->mapped_length);
109 }
110
111 mem_info->mapped_length = 0; /* In case of failure below */
112
113 /* Create a new mapping starting at the address given */
114
115 status = acpi_os_map_memory (address, SYSMEM_REGION_WINDOW_SIZE,
116 (void **) &mem_info->mapped_logical_address);
117 if (ACPI_FAILURE (status)) {
118 return (status);
119 }
120
121 /* TBD: should these pointers go to 64-bit in all cases ? */
122
123 mem_info->mapped_physical_address = address;
124 mem_info->mapped_length = SYSMEM_REGION_WINDOW_SIZE;
125 }
126
127
128 /*
129 * Generate a logical pointer corresponding to the address we want to
130 * access
131 */
132
133 /* TBD: should these pointers go to 64-bit in all cases ? */
134
135 logical_addr_ptr = mem_info->mapped_logical_address +
136 ((ACPI_INTEGER) address - (ACPI_INTEGER) mem_info->mapped_physical_address);
137
138 /* Perform the memory read or write */
139
140 switch (function) {
141
142 case ADDRESS_SPACE_READ:
143
144 switch (bit_width) {
145 case 8:
146 *value = (u32)* (u8 *) logical_addr_ptr;
147 break;
148
149 case 16:
150 MOVE_UNALIGNED16_TO_32 (value, logical_addr_ptr);
151 break;
152
153 case 32:
154 MOVE_UNALIGNED32_TO_32 (value, logical_addr_ptr);
155 break;
156 }
157
158 break;
159
160
161 case ADDRESS_SPACE_WRITE:
162
163 switch (bit_width) {
164 case 8:
165 *(u8 *) logical_addr_ptr = (u8) *value;
166 break;
167
168 case 16:
169 MOVE_UNALIGNED16_TO_16 (logical_addr_ptr, value);
170 break;
171
172 case 32:
173 MOVE_UNALIGNED32_TO_32 (logical_addr_ptr, value);
174 break;
175 }
176
177 break;
178
179
180 default:
181 status = AE_BAD_PARAMETER;
182 break;
183 }
184
185 return (status);
186 }
187
188
189 /*******************************************************************************
190 *
191 * FUNCTION: Acpi_aml_system_io_space_handler
192 *
193 * PARAMETERS: Function - Read or Write operation
194 * Address - Where in the space to read or write
195 * Bit_width - Field width in bits (8, 16, or 32)
196 * Value - Pointer to in or out value
197 * Handler_context - Pointer to Handler's context
198 * Region_context - Pointer to context specific to the
199 * accessed region
200 *
201 * RETURN: Status
202 *
203 * DESCRIPTION: Handler for the System IO address space (Op Region)
204 *
205 ******************************************************************************/
206
207 ACPI_STATUS
208 acpi_aml_system_io_space_handler (
209 u32 function,
210 ACPI_PHYSICAL_ADDRESS address,
211 u32 bit_width,
212 u32 *value,
213 void *handler_context,
214 void *region_context)
215 {
216 ACPI_STATUS status = AE_OK;
217
218
219 /* Decode the function parameter */
220
221 switch (function) {
222
223 case ADDRESS_SPACE_READ:
224
225 switch (bit_width) {
226 /* I/O Port width */
227
228 case 8:
229 *value = (u32) acpi_os_in8 ((ACPI_IO_ADDRESS) address);
230 break;
231
232 case 16:
233 *value = (u32) acpi_os_in16 ((ACPI_IO_ADDRESS) address);
234 break;
235
236 case 32:
237 *value = acpi_os_in32 ((ACPI_IO_ADDRESS) address);
238 break;
239
240 default:
241 status = AE_AML_OPERAND_VALUE;
242 }
243
244 break;
245
246
247 case ADDRESS_SPACE_WRITE:
248
249 switch (bit_width) {
250 /* I/O Port width */
251 case 8:
252 acpi_os_out8 ((ACPI_IO_ADDRESS) address, (u8) *value);
253 break;
254
255 case 16:
256 acpi_os_out16 ((ACPI_IO_ADDRESS) address, (u16) *value);
257 break;
258
259 case 32:
260 acpi_os_out32 ((ACPI_IO_ADDRESS) address, *value);
261 break;
262
263 default:
264 status = AE_AML_OPERAND_VALUE;
265 }
266
267 break;
268
269
270 default:
271 status = AE_BAD_PARAMETER;
272 break;
273 }
274
275 return (status);
276 }
277
278 /*******************************************************************************
279 *
280 * FUNCTION: Acpi_aml_pci_config_space_handler
281 *
282 * PARAMETERS: Function - Read or Write operation
283 * Address - Where in the space to read or write
284 * Bit_width - Field width in bits (8, 16, or 32)
285 * Value - Pointer to in or out value
286 * Handler_context - Pointer to Handler's context
287 * Region_context - Pointer to context specific to the
288 * accessed region
289 *
290 * RETURN: Status
291 *
292 * DESCRIPTION: Handler for the PCI Config address space (Op Region)
293 *
294 ******************************************************************************/
295
296 ACPI_STATUS
297 acpi_aml_pci_config_space_handler (
298 u32 function,
299 ACPI_PHYSICAL_ADDRESS address,
300 u32 bit_width,
301 u32 *value,
302 void *handler_context,
303 void *region_context)
304 {
305 ACPI_STATUS status = AE_OK;
306 u32 pci_bus;
307 u32 dev_func;
308 u8 pci_reg;
309 PCI_HANDLER_CONTEXT *PCIcontext;
310
311
312 /*
313 * The arguments to Acpi_os(Read|Write)Pci_cfg(Byte|Word|Dword) are:
314 *
315 * Seg_bus - 0xSSSSBBBB - SSSS is the PCI bus segment
316 * BBBB is the PCI bus number
317 *
318 * Dev_func - 0xDDDDFFFF - DDDD is the PCI device number
319 * FFFF is the PCI device function number
320 *
321 * Reg_num - Config space register must be < 40h
322 *
323 * Value - input value for write, output for read
324 *
325 */
326
327 PCIcontext = (PCI_HANDLER_CONTEXT *) region_context;
328
329 pci_bus = LOWORD(PCIcontext->seg) << 16;
330 pci_bus |= LOWORD(PCIcontext->bus);
331
332 dev_func = PCIcontext->dev_func;
333
334 pci_reg = (u8) address;
335
336 switch (function) {
337
338 case ADDRESS_SPACE_READ:
339
340 *value = 0;
341
342 switch (bit_width) {
343 /* PCI Register width */
344
345 case 8:
346 status = acpi_os_read_pci_cfg_byte (pci_bus, dev_func, pci_reg,
347 (u8 *) value);
348 break;
349
350 case 16:
351 status = acpi_os_read_pci_cfg_word (pci_bus, dev_func, pci_reg,
352 (u16 *) value);
353 break;
354
355 case 32:
356 status = acpi_os_read_pci_cfg_dword (pci_bus, dev_func, pci_reg,
357 value);
358 break;
359
360 default:
361 status = AE_AML_OPERAND_VALUE;
362
363 } /* Switch bit_width */
364
365 break;
366
367
368 case ADDRESS_SPACE_WRITE:
369
370 switch (bit_width) {
371 /* PCI Register width */
372
373 case 8:
374 status = acpi_os_write_pci_cfg_byte (pci_bus, dev_func, pci_reg,
375 *(u8 *) value);
376 break;
377
378 case 16:
379 status = acpi_os_write_pci_cfg_word (pci_bus, dev_func, pci_reg,
380 *(u16 *) value);
381 break;
382
383 case 32:
384 status = acpi_os_write_pci_cfg_dword (pci_bus, dev_func, pci_reg,
385 *value);
386 break;
387
388 default:
389 status = AE_AML_OPERAND_VALUE;
390
391 } /* Switch bit_width */
392
393 break;
394
395
396 default:
397
398 status = AE_BAD_PARAMETER;
399 break;
400
401 }
402
403 return (status);
404 }
405