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 <contrib/dev/acpica/include/acpi.h>
49#include <contrib/dev/acpica/include/accommon.h>
50#include <contrib/dev/acpica/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
75ACPI_STATUS
76AcpiExSystemMemorySpaceHandler (
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
309ACPI_STATUS
310AcpiExSystemIoSpaceHandler (
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
373ACPI_STATUS
374AcpiExPciConfigSpaceHandler (
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
453ACPI_STATUS
454AcpiExCmosSpaceHandler (
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
490ACPI_STATUS
491AcpiExPciBarSpaceHandler (
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
527ACPI_STATUS
528AcpiExDataTableSpaceHandler (
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