exregion.c revision 1.1.1.2 1
2 /******************************************************************************
3 *
4 * Module Name: exregion - ACPI default OpRegion (address space) handlers
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000 - 2011, Intel Corp.
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 #define __EXREGION_C__
47
48 #include "acpi.h"
49 #include "accommon.h"
50 #include "acinterp.h"
51
52
53 #define _COMPONENT ACPI_EXECUTER
54 ACPI_MODULE_NAME ("exregion")
55
56
57 /*******************************************************************************
58 *
59 * FUNCTION: AcpiExSystemMemorySpaceHandler
60 *
61 * PARAMETERS: Function - Read or Write operation
62 * Address - Where in the space to read or write
63 * BitWidth - Field width in bits (8, 16, or 32)
64 * Value - Pointer to in or out value
65 * HandlerContext - Pointer to Handler's context
66 * RegionContext - Pointer to context specific to the
67 * accessed region
68 *
69 * RETURN: Status
70 *
71 * DESCRIPTION: Handler for the System Memory address space (Op Region)
72 *
73 ******************************************************************************/
74
75 ACPI_STATUS
76 AcpiExSystemMemorySpaceHandler (
77 UINT32 Function,
78 ACPI_PHYSICAL_ADDRESS Address,
79 UINT32 BitWidth,
80 UINT64 *Value,
81 void *HandlerContext,
82 void *RegionContext)
83 {
84 ACPI_STATUS Status = AE_OK;
85 void *LogicalAddrPtr = NULL;
86 ACPI_MEM_SPACE_CONTEXT *MemInfo = RegionContext;
87 UINT32 Length;
88 ACPI_SIZE MapLength;
89 ACPI_SIZE PageBoundaryMapLength;
90 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
91 UINT32 Remainder;
92 #endif
93
94
95 ACPI_FUNCTION_TRACE (ExSystemMemorySpaceHandler);
96
97
98 /* Validate and translate the bit width */
99
100 switch (BitWidth)
101 {
102 case 8:
103 Length = 1;
104 break;
105
106 case 16:
107 Length = 2;
108 break;
109
110 case 32:
111 Length = 4;
112 break;
113
114 case 64:
115 Length = 8;
116 break;
117
118 default:
119 ACPI_ERROR ((AE_INFO, "Invalid SystemMemory width %u",
120 BitWidth));
121 return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
122 }
123
124 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
125 /*
126 * Hardware does not support non-aligned data transfers, we must verify
127 * the request.
128 */
129 (void) AcpiUtShortDivide ((UINT64) Address, Length, NULL, &Remainder);
130 if (Remainder != 0)
131 {
132 return_ACPI_STATUS (AE_AML_ALIGNMENT);
133 }
134 #endif
135
136 /*
137 * Does the request fit into the cached memory mapping?
138 * Is 1) Address below the current mapping? OR
139 * 2) Address beyond the current mapping?
140 */
141 if ((Address < MemInfo->MappedPhysicalAddress) ||
142 (((UINT64) Address + Length) >
143 ((UINT64)
144 MemInfo->MappedPhysicalAddress + MemInfo->MappedLength)))
145 {
146 /*
147 * The request cannot be resolved by the current memory mapping;
148 * Delete the existing mapping and create a new one.
149 */
150 if (MemInfo->MappedLength)
151 {
152 /* Valid mapping, delete it */
153
154 AcpiOsUnmapMemory (MemInfo->MappedLogicalAddress,
155 MemInfo->MappedLength);
156 }
157
158 /*
159 * October 2009: Attempt to map from the requested address to the
160 * end of the region. However, we will never map more than one
161 * page, nor will we cross a page boundary.
162 */
163 MapLength = (ACPI_SIZE)
164 ((MemInfo->Address + MemInfo->Length) - Address);
165
166 /*
167 * If mapping the entire remaining portion of the region will cross
168 * a page boundary, just map up to the page boundary, do not cross.
169 * On some systems, crossing a page boundary while mapping regions
170 * can cause warnings if the pages have different attributes
171 * due to resource management.
172 *
173 * This has the added benefit of constraining a single mapping to
174 * one page, which is similar to the original code that used a 4k
175 * maximum window.
176 */
177 PageBoundaryMapLength =
178 ACPI_ROUND_UP (Address, ACPI_DEFAULT_PAGE_SIZE) - Address;
179 if (PageBoundaryMapLength == 0)
180 {
181 PageBoundaryMapLength = ACPI_DEFAULT_PAGE_SIZE;
182 }
183
184 if (MapLength > PageBoundaryMapLength)
185 {
186 MapLength = PageBoundaryMapLength;
187 }
188
189 /* Create a new mapping starting at the address given */
190
191 MemInfo->MappedLogicalAddress = AcpiOsMapMemory (
192 (ACPI_PHYSICAL_ADDRESS) Address, MapLength);
193 if (!MemInfo->MappedLogicalAddress)
194 {
195 ACPI_ERROR ((AE_INFO,
196 "Could not map memory at 0x%8.8X%8.8X, size %u",
197 ACPI_FORMAT_NATIVE_UINT (Address), (UINT32) MapLength));
198 MemInfo->MappedLength = 0;
199 return_ACPI_STATUS (AE_NO_MEMORY);
200 }
201
202 /* Save the physical address and mapping size */
203
204 MemInfo->MappedPhysicalAddress = Address;
205 MemInfo->MappedLength = MapLength;
206 }
207
208 /*
209 * Generate a logical pointer corresponding to the address we want to
210 * access
211 */
212 LogicalAddrPtr = MemInfo->MappedLogicalAddress +
213 ((UINT64) Address - (UINT64) MemInfo->MappedPhysicalAddress);
214
215 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
216 "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n",
217 BitWidth, Function, ACPI_FORMAT_NATIVE_UINT (Address)));
218
219 /*
220 * Perform the memory read or write
221 *
222 * Note: For machines that do not support non-aligned transfers, the target
223 * address was checked for alignment above. We do not attempt to break the
224 * transfer up into smaller (byte-size) chunks because the AML specifically
225 * asked for a transfer width that the hardware may require.
226 */
227 switch (Function)
228 {
229 case ACPI_READ:
230
231 *Value = 0;
232 switch (BitWidth)
233 {
234 case 8:
235 *Value = (UINT64) ACPI_GET8 (LogicalAddrPtr);
236 break;
237
238 case 16:
239 *Value = (UINT64) ACPI_GET16 (LogicalAddrPtr);
240 break;
241
242 case 32:
243 *Value = (UINT64) ACPI_GET32 (LogicalAddrPtr);
244 break;
245
246 case 64:
247 *Value = (UINT64) ACPI_GET64 (LogicalAddrPtr);
248 break;
249
250 default:
251 /* BitWidth was already validated */
252 break;
253 }
254 break;
255
256 case ACPI_WRITE:
257
258 switch (BitWidth)
259 {
260 case 8:
261 ACPI_SET8 (LogicalAddrPtr) = (UINT8) *Value;
262 break;
263
264 case 16:
265 ACPI_SET16 (LogicalAddrPtr) = (UINT16) *Value;
266 break;
267
268 case 32:
269 ACPI_SET32 ( LogicalAddrPtr) = (UINT32) *Value;
270 break;
271
272 case 64:
273 ACPI_SET64 (LogicalAddrPtr) = (UINT64) *Value;
274 break;
275
276 default:
277 /* BitWidth was already validated */
278 break;
279 }
280 break;
281
282 default:
283 Status = AE_BAD_PARAMETER;
284 break;
285 }
286
287 return_ACPI_STATUS (Status);
288 }
289
290
291 /*******************************************************************************
292 *
293 * FUNCTION: AcpiExSystemIoSpaceHandler
294 *
295 * PARAMETERS: Function - Read or Write operation
296 * Address - Where in the space to read or write
297 * BitWidth - Field width in bits (8, 16, or 32)
298 * Value - Pointer to in or out value
299 * HandlerContext - Pointer to Handler's context
300 * RegionContext - Pointer to context specific to the
301 * accessed region
302 *
303 * RETURN: Status
304 *
305 * DESCRIPTION: Handler for the System IO address space (Op Region)
306 *
307 ******************************************************************************/
308
309 ACPI_STATUS
310 AcpiExSystemIoSpaceHandler (
311 UINT32 Function,
312 ACPI_PHYSICAL_ADDRESS Address,
313 UINT32 BitWidth,
314 UINT64 *Value,
315 void *HandlerContext,
316 void *RegionContext)
317 {
318 ACPI_STATUS Status = AE_OK;
319 UINT32 Value32;
320
321
322 ACPI_FUNCTION_TRACE (ExSystemIoSpaceHandler);
323
324
325 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
326 "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n",
327 BitWidth, Function, ACPI_FORMAT_NATIVE_UINT (Address)));
328
329 /* Decode the function parameter */
330
331 switch (Function)
332 {
333 case ACPI_READ:
334
335 Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) Address,
336 &Value32, BitWidth);
337 *Value = Value32;
338 break;
339
340 case ACPI_WRITE:
341
342 Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) Address,
343 (UINT32) *Value, BitWidth);
344 break;
345
346 default:
347 Status = AE_BAD_PARAMETER;
348 break;
349 }
350
351 return_ACPI_STATUS (Status);
352 }
353
354
355 /*******************************************************************************
356 *
357 * FUNCTION: AcpiExPciConfigSpaceHandler
358 *
359 * PARAMETERS: Function - Read or Write operation
360 * Address - Where in the space to read or write
361 * BitWidth - Field width in bits (8, 16, or 32)
362 * Value - Pointer to in or out value
363 * HandlerContext - Pointer to Handler's context
364 * RegionContext - Pointer to context specific to the
365 * accessed region
366 *
367 * RETURN: Status
368 *
369 * DESCRIPTION: Handler for the PCI Config address space (Op Region)
370 *
371 ******************************************************************************/
372
373 ACPI_STATUS
374 AcpiExPciConfigSpaceHandler (
375 UINT32 Function,
376 ACPI_PHYSICAL_ADDRESS Address,
377 UINT32 BitWidth,
378 UINT64 *Value,
379 void *HandlerContext,
380 void *RegionContext)
381 {
382 ACPI_STATUS Status = AE_OK;
383 ACPI_PCI_ID *PciId;
384 UINT16 PciRegister;
385
386
387 ACPI_FUNCTION_TRACE (ExPciConfigSpaceHandler);
388
389
390 /*
391 * The arguments to AcpiOs(Read|Write)PciConfiguration are:
392 *
393 * PciSegment is the PCI bus segment range 0-31
394 * PciBus is the PCI bus number range 0-255
395 * PciDevice is the PCI device number range 0-31
396 * PciFunction is the PCI device function number
397 * PciRegister is the Config space register range 0-255 bytes
398 *
399 * Value - input value for write, output address for read
400 *
401 */
402 PciId = (ACPI_PCI_ID *) RegionContext;
403 PciRegister = (UINT16) (UINT32) Address;
404
405 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
406 "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
407 Function, BitWidth, PciId->Segment, PciId->Bus, PciId->Device,
408 PciId->Function, PciRegister));
409
410 switch (Function)
411 {
412 case ACPI_READ:
413
414 *Value = 0;
415 Status = AcpiOsReadPciConfiguration (PciId, PciRegister,
416 Value, BitWidth);
417 break;
418
419 case ACPI_WRITE:
420
421 Status = AcpiOsWritePciConfiguration (PciId, PciRegister,
422 *Value, BitWidth);
423 break;
424
425 default:
426
427 Status = AE_BAD_PARAMETER;
428 break;
429 }
430
431 return_ACPI_STATUS (Status);
432 }
433
434
435 /*******************************************************************************
436 *
437 * FUNCTION: AcpiExCmosSpaceHandler
438 *
439 * PARAMETERS: Function - Read or Write operation
440 * Address - Where in the space to read or write
441 * BitWidth - Field width in bits (8, 16, or 32)
442 * Value - Pointer to in or out value
443 * HandlerContext - Pointer to Handler's context
444 * RegionContext - Pointer to context specific to the
445 * accessed region
446 *
447 * RETURN: Status
448 *
449 * DESCRIPTION: Handler for the CMOS address space (Op Region)
450 *
451 ******************************************************************************/
452
453 ACPI_STATUS
454 AcpiExCmosSpaceHandler (
455 UINT32 Function,
456 ACPI_PHYSICAL_ADDRESS Address,
457 UINT32 BitWidth,
458 UINT64 *Value,
459 void *HandlerContext,
460 void *RegionContext)
461 {
462 ACPI_STATUS Status = AE_OK;
463
464
465 ACPI_FUNCTION_TRACE (ExCmosSpaceHandler);
466
467
468 return_ACPI_STATUS (Status);
469 }
470
471
472 /*******************************************************************************
473 *
474 * FUNCTION: AcpiExPciBarSpaceHandler
475 *
476 * PARAMETERS: Function - Read or Write operation
477 * Address - Where in the space to read or write
478 * BitWidth - Field width in bits (8, 16, or 32)
479 * Value - Pointer to in or out value
480 * HandlerContext - Pointer to Handler's context
481 * RegionContext - Pointer to context specific to the
482 * accessed region
483 *
484 * RETURN: Status
485 *
486 * DESCRIPTION: Handler for the PCI BarTarget address space (Op Region)
487 *
488 ******************************************************************************/
489
490 ACPI_STATUS
491 AcpiExPciBarSpaceHandler (
492 UINT32 Function,
493 ACPI_PHYSICAL_ADDRESS Address,
494 UINT32 BitWidth,
495 UINT64 *Value,
496 void *HandlerContext,
497 void *RegionContext)
498 {
499 ACPI_STATUS Status = AE_OK;
500
501
502 ACPI_FUNCTION_TRACE (ExPciBarSpaceHandler);
503
504
505 return_ACPI_STATUS (Status);
506 }
507
508
509 /*******************************************************************************
510 *
511 * FUNCTION: AcpiExDataTableSpaceHandler
512 *
513 * PARAMETERS: Function - Read or Write operation
514 * Address - Where in the space to read or write
515 * BitWidth - Field width in bits (8, 16, or 32)
516 * Value - Pointer to in or out value
517 * HandlerContext - Pointer to Handler's context
518 * RegionContext - Pointer to context specific to the
519 * accessed region
520 *
521 * RETURN: Status
522 *
523 * DESCRIPTION: Handler for the Data Table address space (Op Region)
524 *
525 ******************************************************************************/
526
527 ACPI_STATUS
528 AcpiExDataTableSpaceHandler (
529 UINT32 Function,
530 ACPI_PHYSICAL_ADDRESS Address,
531 UINT32 BitWidth,
532 UINT64 *Value,
533 void *HandlerContext,
534 void *RegionContext)
535 {
536 ACPI_FUNCTION_TRACE (ExDataTableSpaceHandler);
537
538
539 /*
540 * Perform the memory read or write. The BitWidth was already
541 * validated.
542 */
543 switch (Function)
544 {
545 case ACPI_READ:
546
547 ACPI_MEMCPY (ACPI_CAST_PTR (char, Value), ACPI_PHYSADDR_TO_PTR (Address),
548 ACPI_DIV_8 (BitWidth));
549 break;
550
551 case ACPI_WRITE:
552
553 ACPI_MEMCPY (ACPI_PHYSADDR_TO_PTR (Address), ACPI_CAST_PTR (char, Value),
554 ACPI_DIV_8 (BitWidth));
555 break;
556
557 default:
558
559 return_ACPI_STATUS (AE_BAD_PARAMETER);
560 }
561
562 return_ACPI_STATUS (AE_OK);
563 }
564
565
566