]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/dev/acpica/components/hardware/hwxface.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / dev / acpica / components / hardware / hwxface.c
1 /******************************************************************************
2  *
3  * Module Name: hwxface - Public ACPICA hardware interfaces
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2013, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/acnamesp.h>
47
48 #define _COMPONENT          ACPI_HARDWARE
49         ACPI_MODULE_NAME    ("hwxface")
50
51
52 /******************************************************************************
53  *
54  * FUNCTION:    AcpiReset
55  *
56  * PARAMETERS:  None
57  *
58  * RETURN:      Status
59  *
60  * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
61  *              support reset register in PCI config space, this must be
62  *              handled separately.
63  *
64  ******************************************************************************/
65
66 ACPI_STATUS
67 AcpiReset (
68     void)
69 {
70     ACPI_GENERIC_ADDRESS    *ResetReg;
71     ACPI_STATUS             Status;
72
73
74     ACPI_FUNCTION_TRACE (AcpiReset);
75
76
77     ResetReg = &AcpiGbl_FADT.ResetRegister;
78
79     /* Check if the reset register is supported */
80
81     if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
82         !ResetReg->Address)
83     {
84         return_ACPI_STATUS (AE_NOT_EXIST);
85     }
86
87     if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
88     {
89         /*
90          * For I/O space, write directly to the OSL. This bypasses the port
91          * validation mechanism, which may block a valid write to the reset
92          * register.
93          */
94         Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address,
95                     AcpiGbl_FADT.ResetValue, ResetReg->BitWidth);
96     }
97     else
98     {
99         /* Write the reset value to the reset register */
100
101         Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg);
102     }
103
104     return_ACPI_STATUS (Status);
105 }
106
107 ACPI_EXPORT_SYMBOL (AcpiReset)
108
109
110 /******************************************************************************
111  *
112  * FUNCTION:    AcpiRead
113  *
114  * PARAMETERS:  Value               - Where the value is returned
115  *              Reg                 - GAS register structure
116  *
117  * RETURN:      Status
118  *
119  * DESCRIPTION: Read from either memory or IO space.
120  *
121  * LIMITATIONS: <These limitations also apply to AcpiWrite>
122  *      BitWidth must be exactly 8, 16, 32, or 64.
123  *      SpaceID must be SystemMemory or SystemIO.
124  *      BitOffset and AccessWidth are currently ignored, as there has
125  *          not been a need to implement these.
126  *
127  ******************************************************************************/
128
129 ACPI_STATUS
130 AcpiRead (
131     UINT64                  *ReturnValue,
132     ACPI_GENERIC_ADDRESS    *Reg)
133 {
134     UINT32                  ValueLo;
135     UINT32                  ValueHi;
136     UINT32                  Width;
137     UINT64                  Address;
138     ACPI_STATUS             Status;
139
140
141     ACPI_FUNCTION_NAME (AcpiRead);
142
143
144     if (!ReturnValue)
145     {
146         return (AE_BAD_PARAMETER);
147     }
148
149     /* Validate contents of the GAS register. Allow 64-bit transfers */
150
151     Status = AcpiHwValidateRegister (Reg, 64, &Address);
152     if (ACPI_FAILURE (Status))
153     {
154         return (Status);
155     }
156
157     /*
158      * Two address spaces supported: Memory or I/O. PCI_Config is
159      * not supported here because the GAS structure is insufficient
160      */
161     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
162     {
163         Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
164                     Address, ReturnValue, Reg->BitWidth);
165         if (ACPI_FAILURE (Status))
166         {
167             return (Status);
168         }
169     }
170     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
171     {
172         ValueLo = 0;
173         ValueHi = 0;
174
175         Width = Reg->BitWidth;
176         if (Width == 64)
177         {
178             Width = 32; /* Break into two 32-bit transfers */
179         }
180
181         Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
182                     Address, &ValueLo, Width);
183         if (ACPI_FAILURE (Status))
184         {
185             return (Status);
186         }
187
188         if (Reg->BitWidth == 64)
189         {
190             /* Read the top 32 bits */
191
192             Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
193                         (Address + 4), &ValueHi, 32);
194             if (ACPI_FAILURE (Status))
195             {
196                 return (Status);
197             }
198         }
199
200         /* Set the return value only if status is AE_OK */
201
202         *ReturnValue = (ValueLo | ((UINT64) ValueHi << 32));
203     }
204
205     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
206         "Read:  %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
207         ACPI_FORMAT_UINT64 (*ReturnValue), Reg->BitWidth,
208         ACPI_FORMAT_UINT64 (Address),
209         AcpiUtGetRegionName (Reg->SpaceId)));
210
211     return (AE_OK);
212 }
213
214 ACPI_EXPORT_SYMBOL (AcpiRead)
215
216
217 /******************************************************************************
218  *
219  * FUNCTION:    AcpiWrite
220  *
221  * PARAMETERS:  Value               - Value to be written
222  *              Reg                 - GAS register structure
223  *
224  * RETURN:      Status
225  *
226  * DESCRIPTION: Write to either memory or IO space.
227  *
228  ******************************************************************************/
229
230 ACPI_STATUS
231 AcpiWrite (
232     UINT64                  Value,
233     ACPI_GENERIC_ADDRESS    *Reg)
234 {
235     UINT32                  Width;
236     UINT64                  Address;
237     ACPI_STATUS             Status;
238
239
240     ACPI_FUNCTION_NAME (AcpiWrite);
241
242
243     /* Validate contents of the GAS register. Allow 64-bit transfers */
244
245     Status = AcpiHwValidateRegister (Reg, 64, &Address);
246     if (ACPI_FAILURE (Status))
247     {
248         return (Status);
249     }
250
251     /*
252      * Two address spaces supported: Memory or IO. PCI_Config is
253      * not supported here because the GAS structure is insufficient
254      */
255     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
256     {
257         Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS)
258                     Address, Value, Reg->BitWidth);
259         if (ACPI_FAILURE (Status))
260         {
261             return (Status);
262         }
263     }
264     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
265     {
266         Width = Reg->BitWidth;
267         if (Width == 64)
268         {
269             Width = 32; /* Break into two 32-bit transfers */
270         }
271
272         Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
273                     Address, ACPI_LODWORD (Value), Width);
274         if (ACPI_FAILURE (Status))
275         {
276             return (Status);
277         }
278
279         if (Reg->BitWidth == 64)
280         {
281             Status = AcpiHwWritePort ((ACPI_IO_ADDRESS)
282                         (Address + 4), ACPI_HIDWORD (Value), 32);
283             if (ACPI_FAILURE (Status))
284             {
285                 return (Status);
286             }
287         }
288     }
289
290     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
291         "Wrote: %8.8X%8.8X width %2d   to %8.8X%8.8X (%s)\n",
292         ACPI_FORMAT_UINT64 (Value), Reg->BitWidth,
293         ACPI_FORMAT_UINT64 (Address),
294         AcpiUtGetRegionName (Reg->SpaceId)));
295
296     return (Status);
297 }
298
299 ACPI_EXPORT_SYMBOL (AcpiWrite)
300
301
302 #if (!ACPI_REDUCED_HARDWARE)
303 /*******************************************************************************
304  *
305  * FUNCTION:    AcpiReadBitRegister
306  *
307  * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
308  *              ReturnValue     - Value that was read from the register,
309  *                                normalized to bit position zero.
310  *
311  * RETURN:      Status and the value read from the specified Register. Value
312  *              returned is normalized to bit0 (is shifted all the way right)
313  *
314  * DESCRIPTION: ACPI BitRegister read function. Does not acquire the HW lock.
315  *
316  * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
317  *              PM2 Control.
318  *
319  * Note: The hardware lock is not required when reading the ACPI bit registers
320  *       since almost all of them are single bit and it does not matter that
321  *       the parent hardware register can be split across two physical
322  *       registers. The only multi-bit field is SLP_TYP in the PM1 control
323  *       register, but this field does not cross an 8-bit boundary (nor does
324  *       it make much sense to actually read this field.)
325  *
326  ******************************************************************************/
327
328 ACPI_STATUS
329 AcpiReadBitRegister (
330     UINT32                  RegisterId,
331     UINT32                  *ReturnValue)
332 {
333     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
334     UINT32                  RegisterValue;
335     UINT32                  Value;
336     ACPI_STATUS             Status;
337
338
339     ACPI_FUNCTION_TRACE_U32 (AcpiReadBitRegister, RegisterId);
340
341
342     /* Get the info structure corresponding to the requested ACPI Register */
343
344     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
345     if (!BitRegInfo)
346     {
347         return_ACPI_STATUS (AE_BAD_PARAMETER);
348     }
349
350     /* Read the entire parent register */
351
352     Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
353                 &RegisterValue);
354     if (ACPI_FAILURE (Status))
355     {
356         return_ACPI_STATUS (Status);
357     }
358
359     /* Normalize the value that was read, mask off other bits */
360
361     Value = ((RegisterValue & BitRegInfo->AccessBitMask)
362                 >> BitRegInfo->BitPosition);
363
364     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
365         "BitReg %X, ParentReg %X, Actual %8.8X, ReturnValue %8.8X\n",
366         RegisterId, BitRegInfo->ParentRegister, RegisterValue, Value));
367
368     *ReturnValue = Value;
369     return_ACPI_STATUS (AE_OK);
370 }
371
372 ACPI_EXPORT_SYMBOL (AcpiReadBitRegister)
373
374
375 /*******************************************************************************
376  *
377  * FUNCTION:    AcpiWriteBitRegister
378  *
379  * PARAMETERS:  RegisterId      - ID of ACPI Bit Register to access
380  *              Value           - Value to write to the register, in bit
381  *                                position zero. The bit is automatically
382  *                                shifted to the correct position.
383  *
384  * RETURN:      Status
385  *
386  * DESCRIPTION: ACPI Bit Register write function. Acquires the hardware lock
387  *              since most operations require a read/modify/write sequence.
388  *
389  * SUPPORTS:    Bit fields in PM1 Status, PM1 Enable, PM1 Control, and
390  *              PM2 Control.
391  *
392  * Note that at this level, the fact that there may be actually two
393  * hardware registers (A and B - and B may not exist) is abstracted.
394  *
395  ******************************************************************************/
396
397 ACPI_STATUS
398 AcpiWriteBitRegister (
399     UINT32                  RegisterId,
400     UINT32                  Value)
401 {
402     ACPI_BIT_REGISTER_INFO  *BitRegInfo;
403     ACPI_CPU_FLAGS          LockFlags;
404     UINT32                  RegisterValue;
405     ACPI_STATUS             Status = AE_OK;
406
407
408     ACPI_FUNCTION_TRACE_U32 (AcpiWriteBitRegister, RegisterId);
409
410
411     /* Get the info structure corresponding to the requested ACPI Register */
412
413     BitRegInfo = AcpiHwGetBitRegisterInfo (RegisterId);
414     if (!BitRegInfo)
415     {
416         return_ACPI_STATUS (AE_BAD_PARAMETER);
417     }
418
419     LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock);
420
421     /*
422      * At this point, we know that the parent register is one of the
423      * following: PM1 Status, PM1 Enable, PM1 Control, or PM2 Control
424      */
425     if (BitRegInfo->ParentRegister != ACPI_REGISTER_PM1_STATUS)
426     {
427         /*
428          * 1) Case for PM1 Enable, PM1 Control, and PM2 Control
429          *
430          * Perform a register read to preserve the bits that we are not
431          * interested in
432          */
433         Status = AcpiHwRegisterRead (BitRegInfo->ParentRegister,
434                     &RegisterValue);
435         if (ACPI_FAILURE (Status))
436         {
437             goto UnlockAndExit;
438         }
439
440         /*
441          * Insert the input bit into the value that was just read
442          * and write the register
443          */
444         ACPI_REGISTER_INSERT_VALUE (RegisterValue, BitRegInfo->BitPosition,
445             BitRegInfo->AccessBitMask, Value);
446
447         Status = AcpiHwRegisterWrite (BitRegInfo->ParentRegister,
448                     RegisterValue);
449     }
450     else
451     {
452         /*
453          * 2) Case for PM1 Status
454          *
455          * The Status register is different from the rest. Clear an event
456          * by writing 1, writing 0 has no effect. So, the only relevant
457          * information is the single bit we're interested in, all others
458          * should be written as 0 so they will be left unchanged.
459          */
460         RegisterValue = ACPI_REGISTER_PREPARE_BITS (Value,
461             BitRegInfo->BitPosition, BitRegInfo->AccessBitMask);
462
463         /* No need to write the register if value is all zeros */
464
465         if (RegisterValue)
466         {
467             Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS,
468                         RegisterValue);
469         }
470     }
471
472     ACPI_DEBUG_PRINT ((ACPI_DB_IO,
473         "BitReg %X, ParentReg %X, Value %8.8X, Actual %8.8X\n",
474         RegisterId, BitRegInfo->ParentRegister, Value, RegisterValue));
475
476
477 UnlockAndExit:
478
479     AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags);
480     return_ACPI_STATUS (Status);
481 }
482
483 ACPI_EXPORT_SYMBOL (AcpiWriteBitRegister)
484
485 #endif /* !ACPI_REDUCED_HARDWARE */
486
487
488 /*******************************************************************************
489  *
490  * FUNCTION:    AcpiGetSleepTypeData
491  *
492  * PARAMETERS:  SleepState          - Numeric sleep state
493  *              *SleepTypeA         - Where SLP_TYPa is returned
494  *              *SleepTypeB         - Where SLP_TYPb is returned
495  *
496  * RETURN:      Status
497  *
498  * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested
499  *              sleep state via the appropriate \_Sx object.
500  *
501  *  The sleep state package returned from the corresponding \_Sx_ object
502  *  must contain at least one integer.
503  *
504  *  March 2005:
505  *  Added support for a package that contains two integers. This
506  *  goes against the ACPI specification which defines this object as a
507  *  package with one encoded DWORD integer. However, existing practice
508  *  by many BIOS vendors is to return a package with 2 or more integer
509  *  elements, at least one per sleep type (A/B).
510  *
511  *  January 2013:
512  *  Therefore, we must be prepared to accept a package with either a
513  *  single integer or multiple integers.
514  *
515  *  The single integer DWORD format is as follows:
516  *      BYTE 0 - Value for the PM1A SLP_TYP register
517  *      BYTE 1 - Value for the PM1B SLP_TYP register
518  *      BYTE 2-3 - Reserved
519  *
520  *  The dual integer format is as follows:
521  *      Integer 0 - Value for the PM1A SLP_TYP register
522  *      Integer 1 - Value for the PM1A SLP_TYP register
523  *
524  ******************************************************************************/
525
526 ACPI_STATUS
527 AcpiGetSleepTypeData (
528     UINT8                   SleepState,
529     UINT8                   *SleepTypeA,
530     UINT8                   *SleepTypeB)
531 {
532     ACPI_STATUS             Status;
533     ACPI_EVALUATE_INFO      *Info;
534     ACPI_OPERAND_OBJECT     **Elements;
535
536
537     ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
538
539
540     /* Validate parameters */
541
542     if ((SleepState > ACPI_S_STATES_MAX) ||
543         !SleepTypeA || !SleepTypeB)
544     {
545         return_ACPI_STATUS (AE_BAD_PARAMETER);
546     }
547
548     /* Allocate the evaluation information block */
549
550     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
551     if (!Info)
552     {
553         return_ACPI_STATUS (AE_NO_MEMORY);
554     }
555
556     /*
557      * Evaluate the \_Sx namespace object containing the register values
558      * for this state
559      */
560     Info->RelativePathname = ACPI_CAST_PTR (
561         char, AcpiGbl_SleepStateNames[SleepState]);
562     Status = AcpiNsEvaluate (Info);
563     if (ACPI_FAILURE (Status))
564     {
565         goto Cleanup;
566     }
567
568     /* Must have a return object */
569
570     if (!Info->ReturnObject)
571     {
572         ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
573             Info->RelativePathname));
574         Status = AE_AML_NO_RETURN_VALUE;
575         goto Cleanup;
576     }
577
578     /* Return object must be of type Package */
579
580     if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
581     {
582         ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
583         Status = AE_AML_OPERAND_TYPE;
584         goto Cleanup1;
585     }
586
587     /*
588      * Any warnings about the package length or the object types have
589      * already been issued by the predefined name module -- there is no
590      * need to repeat them here.
591      */
592     Elements = Info->ReturnObject->Package.Elements;
593     switch (Info->ReturnObject->Package.Count)
594     {
595     case 0:
596
597         Status = AE_AML_PACKAGE_LIMIT;
598         break;
599
600     case 1:
601
602         if (Elements[0]->Common.Type != ACPI_TYPE_INTEGER)
603         {
604             Status = AE_AML_OPERAND_TYPE;
605             break;
606         }
607
608         /* A valid _Sx_ package with one integer */
609
610         *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
611         *SleepTypeB = (UINT8) (Elements[0]->Integer.Value >> 8);
612         break;
613
614     case 2:
615     default:
616
617         if ((Elements[0]->Common.Type != ACPI_TYPE_INTEGER) ||
618             (Elements[1]->Common.Type != ACPI_TYPE_INTEGER))
619         {
620             Status = AE_AML_OPERAND_TYPE;
621             break;
622         }
623
624         /* A valid _Sx_ package with two integers */
625
626         *SleepTypeA = (UINT8) Elements[0]->Integer.Value;
627         *SleepTypeB = (UINT8) Elements[1]->Integer.Value;
628         break;
629     }
630
631 Cleanup1:
632     AcpiUtRemoveReference (Info->ReturnObject);
633
634 Cleanup:
635     if (ACPI_FAILURE (Status))
636     {
637         ACPI_EXCEPTION ((AE_INFO, Status,
638             "While evaluating Sleep State [%s]", Info->RelativePathname));
639     }
640
641     ACPI_FREE (Info);
642     return_ACPI_STATUS (Status);
643 }
644
645 ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)