]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/components/hardware/hwxface.c
Update to tcsh 6.18.01.
[FreeBSD/FreeBSD.git] / sys / contrib / dev / acpica / components / hardware / hwxface.c
1
2 /******************************************************************************
3  *
4  * Module Name: hwxface - Public ACPICA hardware interfaces
5  *
6  *****************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2012, 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 #include <contrib/dev/acpica/include/acpi.h>
46 #include <contrib/dev/acpica/include/accommon.h>
47 #include <contrib/dev/acpica/include/acnamesp.h>
48
49 #define _COMPONENT          ACPI_HARDWARE
50         ACPI_MODULE_NAME    ("hwxface")
51
52
53 /******************************************************************************
54  *
55  * FUNCTION:    AcpiReset
56  *
57  * PARAMETERS:  None
58  *
59  * RETURN:      Status
60  *
61  * DESCRIPTION: Set reset register in memory or IO space. Note: Does not
62  *              support reset register in PCI config space, this must be
63  *              handled separately.
64  *
65  ******************************************************************************/
66
67 ACPI_STATUS
68 AcpiReset (
69     void)
70 {
71     ACPI_GENERIC_ADDRESS    *ResetReg;
72     ACPI_STATUS             Status;
73
74
75     ACPI_FUNCTION_TRACE (AcpiReset);
76
77
78     ResetReg = &AcpiGbl_FADT.ResetRegister;
79
80     /* Check if the reset register is supported */
81
82     if (!(AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) ||
83         !ResetReg->Address)
84     {
85         return_ACPI_STATUS (AE_NOT_EXIST);
86     }
87
88     if (ResetReg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO)
89     {
90         /*
91          * For I/O space, write directly to the OSL. This bypasses the port
92          * validation mechanism, which may block a valid write to the reset
93          * register.
94          */
95         Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address,
96                     AcpiGbl_FADT.ResetValue, ResetReg->BitWidth);
97     }
98     else
99     {
100         /* Write the reset value to the reset register */
101
102         Status = AcpiHwWrite (AcpiGbl_FADT.ResetValue, ResetReg);
103     }
104
105     return_ACPI_STATUS (Status);
106 }
107
108 ACPI_EXPORT_SYMBOL (AcpiReset)
109
110
111 /******************************************************************************
112  *
113  * FUNCTION:    AcpiRead
114  *
115  * PARAMETERS:  Value               - Where the value is returned
116  *              Reg                 - GAS register structure
117  *
118  * RETURN:      Status
119  *
120  * DESCRIPTION: Read from either memory or IO space.
121  *
122  * LIMITATIONS: <These limitations also apply to AcpiWrite>
123  *      BitWidth must be exactly 8, 16, 32, or 64.
124  *      SpaceID must be SystemMemory or SystemIO.
125  *      BitOffset and AccessWidth are currently ignored, as there has
126  *          not been a need to implement these.
127  *
128  ******************************************************************************/
129
130 ACPI_STATUS
131 AcpiRead (
132     UINT64                  *ReturnValue,
133     ACPI_GENERIC_ADDRESS    *Reg)
134 {
135     UINT32                  Value;
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     /* Initialize entire 64-bit return value to zero */
158
159     *ReturnValue = 0;
160     Value = 0;
161
162     /*
163      * Two address spaces supported: Memory or IO. PCI_Config is
164      * not supported here because the GAS structure is insufficient
165      */
166     if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY)
167     {
168         Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS)
169                     Address, ReturnValue, Reg->BitWidth);
170         if (ACPI_FAILURE (Status))
171         {
172             return (Status);
173         }
174     }
175     else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
176     {
177         Width = Reg->BitWidth;
178         if (Width == 64)
179         {
180             Width = 32; /* Break into two 32-bit transfers */
181         }
182
183         Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
184                     Address, &Value, Width);
185         if (ACPI_FAILURE (Status))
186         {
187             return (Status);
188         }
189         *ReturnValue = Value;
190
191         if (Reg->BitWidth == 64)
192         {
193             /* Read the top 32 bits */
194
195             Status = AcpiHwReadPort ((ACPI_IO_ADDRESS)
196                         (Address + 4), &Value, 32);
197             if (ACPI_FAILURE (Status))
198             {
199                 return (Status);
200             }
201             *ReturnValue |= ((UINT64) Value << 32);
202         }
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 (Status);
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 automaticallly
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 - ACPI status
497  *
498  * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested sleep
499  *              state.
500  *
501  ******************************************************************************/
502
503 ACPI_STATUS
504 AcpiGetSleepTypeData (
505     UINT8                   SleepState,
506     UINT8                   *SleepTypeA,
507     UINT8                   *SleepTypeB)
508 {
509     ACPI_STATUS             Status = AE_OK;
510     ACPI_EVALUATE_INFO      *Info;
511
512
513     ACPI_FUNCTION_TRACE (AcpiGetSleepTypeData);
514
515
516     /* Validate parameters */
517
518     if ((SleepState > ACPI_S_STATES_MAX) ||
519         !SleepTypeA ||
520         !SleepTypeB)
521     {
522         return_ACPI_STATUS (AE_BAD_PARAMETER);
523     }
524
525     /* Allocate the evaluation information block */
526
527     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
528     if (!Info)
529     {
530         return_ACPI_STATUS (AE_NO_MEMORY);
531     }
532
533     Info->Pathname = ACPI_CAST_PTR (char, AcpiGbl_SleepStateNames[SleepState]);
534
535     /* Evaluate the namespace object containing the values for this state */
536
537     Status = AcpiNsEvaluate (Info);
538     if (ACPI_FAILURE (Status))
539     {
540         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
541             "%s while evaluating SleepState [%s]\n",
542             AcpiFormatException (Status), Info->Pathname));
543
544         goto Cleanup;
545     }
546
547     /* Must have a return object */
548
549     if (!Info->ReturnObject)
550     {
551         ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]",
552             Info->Pathname));
553         Status = AE_NOT_EXIST;
554     }
555
556     /* It must be of type Package */
557
558     else if (Info->ReturnObject->Common.Type != ACPI_TYPE_PACKAGE)
559     {
560         ACPI_ERROR ((AE_INFO, "Sleep State return object is not a Package"));
561         Status = AE_AML_OPERAND_TYPE;
562     }
563
564     /*
565      * The package must have at least two elements. NOTE (March 2005): This
566      * goes against the current ACPI spec which defines this object as a
567      * package with one encoded DWORD element. However, existing practice
568      * by BIOS vendors seems to be to have 2 or more elements, at least
569      * one per sleep type (A/B).
570      */
571     else if (Info->ReturnObject->Package.Count < 2)
572     {
573         ACPI_ERROR ((AE_INFO,
574             "Sleep State return package does not have at least two elements"));
575         Status = AE_AML_NO_OPERAND;
576     }
577
578     /* The first two elements must both be of type Integer */
579
580     else if (((Info->ReturnObject->Package.Elements[0])->Common.Type
581                 != ACPI_TYPE_INTEGER) ||
582              ((Info->ReturnObject->Package.Elements[1])->Common.Type
583                 != ACPI_TYPE_INTEGER))
584     {
585         ACPI_ERROR ((AE_INFO,
586             "Sleep State return package elements are not both Integers "
587             "(%s, %s)",
588             AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[0]),
589             AcpiUtGetObjectTypeName (Info->ReturnObject->Package.Elements[1])));
590         Status = AE_AML_OPERAND_TYPE;
591     }
592     else
593     {
594         /* Valid _Sx_ package size, type, and value */
595
596         *SleepTypeA = (UINT8)
597             (Info->ReturnObject->Package.Elements[0])->Integer.Value;
598         *SleepTypeB = (UINT8)
599             (Info->ReturnObject->Package.Elements[1])->Integer.Value;
600     }
601
602     if (ACPI_FAILURE (Status))
603     {
604         ACPI_EXCEPTION ((AE_INFO, Status,
605             "While evaluating SleepState [%s], bad Sleep object %p type %s",
606             Info->Pathname, Info->ReturnObject,
607             AcpiUtGetObjectTypeName (Info->ReturnObject)));
608     }
609
610     AcpiUtRemoveReference (Info->ReturnObject);
611
612 Cleanup:
613     ACPI_FREE (Info);
614     return_ACPI_STATUS (Status);
615 }
616
617 ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData)