xref: /titanic_51/usr/src/uts/intel/io/acpica/executer/exregion.c (revision bbaa8b60dd95d714741fc474adad3cf710ef4efd)
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